La respuesta de John Deters explica por qué usar más dígitos para los códigos 2FA es bueno, pero no lo ha hecho. Mostró las matemáticas. Además, invita a los lectores a revisar sus cálculos, y creo que hay algunos errores. Quería hacer una edición, pero me di cuenta de que sería demasiado tiempo. Así que estoy publicando esto como una respuesta separada; si hay consenso en que mis cálculos son correctos, podemos editar su respuesta (o él puede hacerlo él mismo).
El objetivo es calcular cuántos intentos necesita un atacante para adivinar un código 2FA de una longitud determinada. El atacante tiene éxito si, haciendo varios intentos, puede adivinar al menos uno. "Al menos 1" es difícil de calcular directamente, así que vamos a usar un truco:
P(at least one code is guessed) = 1 - P(no codes are guessed)
Ahora, de la fórmula binomial , la probabilidad de obtener exactamente k=0
successes en n
trial es simplemente
(1-p)^n
entonces
P(at least one code is guessed) = 1 - (1-p)^n
Entonces, para un p=3/1000
dado (3 intentos antes de que la cuenta se bloquee, donde el total de códigos de 3 dígitos posibles son 1000), ¿cuál es el número de intentos n
que un atacante necesita para tener una probabilidad de éxito? mayor del 50%?
P(at least one code is guessed) > 50%
1 - (1-p)^n > 50%
(1-p)^n < (1 - 50%)
(Lo dejo como 1 - 50%
, en lugar de reemplazarlo con el resultado 1/2, porque al final repetiremos el cálculo para tener una probabilidad del 99%, y en ese caso lo quiero para que quede claro que no tenemos que escribir 0.99, sino 0.01. Podría haber dejado una variable allí, como desired_success_probability , pero pensé que sería menos legible)
Ahora, para extraer n
, vamos a llevar el logaritmo a la base (1-p) de ambos miembros. Dado que la base es menor que 1, y la función logarítmica para una base menor que 1 es disminuyendo monotónicamente , tenemos para invertir la desigualdad , por lo que obtenemos:
n > log (1-p) (1 - 50%)
y cambiando la base a una conveniente (por ejemplo, 10 o e
-
todo vale, siempre que la calculadora lo soporte) tenemos la solución:
n > log(1-50%) / log(1-p)
que para p = 3/1000 es
n > 230.7, that is, n >= 231.
Entonces, si la probabilidad de adivinar un código es 3/1000, después de 231 intentos, tenemos que adivinar que al menos uno es más probable que adivinar ninguno.
Si, en lugar de tener una probabilidad de éxito del 50%, el atacante desea alcanzar el 99%, necesita
n > log(1-99%) / log(1-p)
que significa
n > 1532.75, that is, n >= 1533
Y si el atacante puede hacer 3 intentos por cuenta antes de que se bloquee, significa que solo necesita 77 cuentas en su base de datos robada para tener una probabilidad de más del 50% de dividirse en una, o 511 para tener más de 99%.
¿Qué sucede si el código 2FA tiene, en cambio, 6 dígitos? La probabilidad de éxito para un solo intento se convierte en p = 3/1,000,000
, lo que significa que el atacante necesita al menos 231,049 intentos (77017 cuentas) para tener un 50% de probabilidad de éxito. Si quiere tener un 99% de posibilidades de éxito, necesita 1,535,055 intentos (511,685 cuentas).
En resumen, al agregar 3 dígitos estamos aumentando el número de códigos posibles en un factor de 1000, y para mantener la misma probabilidad de éxito, el atacante debe hacer un poco más de 1000 veces más intentos. Si estas son cuentas bancarias en línea, ¿vale la pena gastar de 1 a 2 segundos más para ingresar el código y hacer que la vida de un ladrón sea 1000 veces más difícil? En mi opinión, absolutamente.