# How long should 2 factor authentication codes be?

I've noticed that many services that offer 2 factor authentication have jumped from using four digits to six. However, it seems counterproductive to me because the digits are random, the digits (should) expire, and with six digits, you may have to look at your phone twice or more

Is there any reason for this, beyond it seeming more secure? My preference would be four or even three digits as they are easier to remember and re-enter.

• As is often the case, this is a security vs usability case: more digits and shorter intervals means higher security but lower usability, while less digits and longer intervals means higher usability but lower security. Something like 6 digits and 30 second intervals seems to be considered by most as a good balance of the two. Aug 22, 2017 at 0:29
• Easier to remember and re-enter in the case of a 30-second OTP window is not exactly a difficult proposition, mind you. Even the stronger six digit codes most commonly found are not difficult to enter in that time. Memory is irrelevant in this kind of authentication stage too as you would be staring at the number. Aug 23, 2017 at 0:10

Yes, there is a reason - to reduce brute force guessing attacks against multiple accounts.

All 2FA implementations include an online component that enforces a limited set of retries, ensuring the account is locked out long before an attacker could try all possible passcodes. The length of the 2FA passcode establishes the probability of a malicious actor guessing the authentication in the given number of attempts allowed. For example, if the 2FA passcode is 3 digits long and you are given 3 attempts to enter it, the chances of randomly guessing it are 3/1000, or 0.33%. If the 2FA passcode is 4 digits long, the chances drop to 3/10000, or 0.033%.

While this is certainly a low chance that he'll guess your specific passcode, imagine an attacker with a database of 10,000 accounts stolen from some server. Attacking just one user account, he only has a 0.33% chance of guessing it, but after guessing three times each on 509 different accounts, the probability he'll successfully guess one is 0.5, or 50%. By the time he's locked out 2,009 accounts, the probability he successfully guessed at least one valid passcode is .99, or 99%.* Consider the attacker may not need to successfully attack all accounts in order to gain access - he may only need one success in order to log in to the site and establish a foothold.

Traditionally, detecting a brute force attack relied on recognizing the attacker trying multiple requests quickly with an automated script. An IP address that is responsible for three or ten locked-out accounts in a row might trigger an alert. But modern attackers know that by proceeding slowly they can avoid detection; recent advanced attacks have demonstrated this technique in the wild. Consider an attacker using a botnet of 10,000 zombie computers. He can command them to slowly launch one random request every few minutes from all 10,000 IP addresses without ever tripping a velocity alert or locking out any account. It's only a matter of time before he succeeds.

Since detection of this attack is virtually impossible, the only protections left are to make it harder on the attacker, so the odds of correctly guessing a passcode must be reduced. The two ways to do that are to increase the minimum length of a passcode (to 6 or 8 digits,) or to reduce the number of invalid passcode attempts allowed. Since reducing the number of guesses would impact usability for the legitimate users, algorithm designers have little choice but to increase the length of each passcode.

* My math skills are not great, so these numbers may be off. Some mathematically inclined editor should feel free edit this answer to include the proof by correctly using the Bernoulli formula.

• I've posted an answer that focuses on the maths. My results are different from yours, would you mind having a look at my calculations? Aug 23, 2017 at 0:20

John Deters's answer explains why using more digits for 2FA codes is a good thing, but he hasn't shown the math. Moreover, he invites readers to check his calculations, and I think there are some errors. I wanted to make an edit, but I've realised it would be way too long. So I'm posting this as a separate answer; if there is consensus that my calculations are right, we can edit his answer (or he can do it himself).

The goal is to calculate how many attempts an attacker needs to guess a 2FA code of a given length. The attacker succeeds if, making several attempts, he can guess at least one. "At least 1" is hard to calculate directly, so let's use a trick:

``````P(at least one code is guessed) = 1 - P(no codes are guessed)
``````

Now, from the binomial formula, the probability of getting exactly `k=0` successes in `n` trials is simply

``````(1-p)^n
``````

so

``````P(at least one code is guessed) = 1 - (1-p)^n
``````

So, for a given `p=3/1000` (3 attempts before the account is locked, where the total possible 3-digit codes are 1000), what's the number of attempts `n` that an attacker needs to have a probability of success greater than 50%?

``````P(at least one code is guessed) > 50%
1 - (1-p)^n > 50%
(1-p)^n < (1 - 50%)
``````

(I'm leaving it as `1 - 50%`, instead of replacing it with the result 1/2, because at the end we'll repeat the calculation to have a probability of 99%, and in that case I want it to be clear that we don't have to write 0.99, but rather 0.01. I could have left a variable there, like desired_success_probability, but I thought it would be less readable)

Now, to extract `n`, let's take the logarithm to base (1-p) of both members. Since the base is less than 1, and the logarithmic function to a base less than 1 is monotonically decreasing, we have to invert the inequality, so we get:

n > log(1-p)(1 - 50%)

and by changing the base to a convenient one (for example 10 or `e` - anything goes, as long as the calculator supports it) we have the solution:

``````n > log(1-50%) / log(1-p)
``````

which for p=3/1000 is

``````n > 230.7, that is, n >= 231.
``````

So if the probability of guessing one code is 3/1000, after 231 attempts we have that guessing at least one is more likely than guessing none.

If, instead of having a probability of success of 50%, the attacker wants to reach 99%, he needs

``````n > log(1-99%) / log(1-p)
``````

which means

``````n > 1532.75, that is, n >= 1533
``````

And if the attacker can make 3 attempts per account before it gets locked, it means that he only needs 77 accounts in his stolen database to have a probability of more than 50% to break into one, or 511 to have more than 99%.

What happens if the 2FA code is, instead, 6 digits long? The probability of success for a single attempt becomes `p = 3/1,000,000`, which means that the attacker needs at least 231,049 attempts (77017 accounts) to have a 50% chance of success. If he wants to have a 99% chance of success, he needs 1,535,055 attempts (511,685 accounts).

In short, by adding 3 digits we are increasing the number of possible codes by a factor of 1000, and to keep the same probability of success the attacker needs to make slightly more than 1000 times as many attempts. If these are online banking accounts, is it worth it to spend 1-2 seconds more to enter the code in order to make a thief's life 1000 times harder? In my opinion, absolutely.

• Thank you Fabio! This is exactly the information I was hoping for! Aug 23, 2017 at 2:59
• Looks to me like you're doing the "3 tries per account" twice, and incorrectly the second time. `log(.01)/log(1-3/1000) ~= 1533` for 99% with 3 tries, looks like your 511 comes from `log(.01)/log(1-3/1000)/3 ~= 511` when it would actually be `log(.01)/log(1-9/1000) ~= 510`. Aug 23, 2017 at 13:45
• To clarify since I didn't make it clear, if each account got 3*3=9 tries I'm saying you'd need 510 accounts for 99% probability of guessing one rather than 511, but regardless it's 9 tries for that, not 3. Aug 23, 2017 at 19:05
• @AndrolGenhald I'm not sure I follow you, but now that I'm thinking more about it, I suspect there is indeed an error. I'm pretty confused right now, I'll try to think about it again tomorrow. Or maybe I'll ask for help on math stack exchange... Aug 23, 2017 at 22:55
• Towards the top you say `p=3/1000` for 3 attempts with 1000 possibilities, getting 231 and 1533 for probabilities 50% and 99%, then towards the bottom you give the answers 77 and 511 for 3 attempts, presumably by dividing your previous answers by 3, but your first answers were already for 3 attempts. Aug 24, 2017 at 4:22