I was wondering if there is a formula to calculate how long it would take to "guess" a "X-Digit" OTP, presuming you limited the number of times you can try for each code and the number of codes you can get over a period of time.
For example:
- I have a 6-digit code
- I can try to verify the code 3 times before it becomes invalid
- I can generate 10 codes per hour (so 30 attempts per hour)
- Each code is generated using a cryptographically secure random generator
To go through the 1 million possibilities, I would have to spend 33,333 hours or about 3.8 years.
I'm not an expert in statistics but since every code is random, you might never find the number even if you go through all possibilities.
So what would be the proper way to calculate this?
I tried to apply Calculating the time required to brute force a random code but I couldn't get the formula to work for some reasons
In your example, we can think about it as follows:
A six-digit code has 1,000,000 possible states, hence allows for a 1/1,000,000 chance to correctly guess it on the first try. Given that we can try thrice, the second chance is 1 / 999,999 and the third is 1 / 999,998. Although, the numbers are too close to 3/1,000,000 for it to make statistical difference.
So we can say, for one generated code, our chance is 3/1,000,000. That means, plugging into the formula 1-(1-p)^n = x, we get an n of ≈231,049 codes to generate for a 50% chance of cracking it.
In other words: If 231,049 different hackers each tried to hack a six-digit code by choosing 3 random codes, then about half of them would succeed.
Since we can do this 10 times an hour, we can conveniently just divide this by 10 to see how many hours it'd take, which is 23,105 hours, or about 2.6 years.
This is actually slightly better than your estimate.
Why does it not align with the linked calculation?
This is because you're not sufficiently exhausting the keyspace. As I said in the beginning, the second and third guess are slightly more likely to succeed than the first one, because you already know one code that isn't correct, and later two.
However, on your third wrong guess, the code becomes invalid and you are back at the beginning. For this reason, you have to use a different formula, which calculates the cumulative chance of independent events, rather than simply checking how large the keyspace is and dividing it in half.
Regarding the real world
In real life, it's likely even more difficult to be successful, because repeatedly entering wrong one-time codes could lock the account, or the service could notify the user that their account is likely compromised, which leads to them changing their password.
In short, OTP codes like this are not bullet-proof and can be guessed by sheer luck, but it's very unlikely to lead to consistent success.
Increasing Security
This scheme is already plenty secure - secure enough that PayPal uses it - but if you want to go even further, you could make the codes longer. 8 digits would turn 2.6 years to 260 years (roughly), and adding even some uppercase letters to it would make the keyspace even larger.
The downside would be a worse user experience, as "632 109" is slightly easier to type than "P88X 6A3H". It would risk users not enabling 2FA at all, all for making a theoretical attack theoretically more difficult.