Genera y valida contrasenas de un solo uso basadas en tiempo (TOTP) a partir de un secreto base32. Compatible con Google Authenticator y RFC 6238.
Contrasenas de un solo uso, RFC 6238. Genera el TOTP actual de un secreto base32 y valida un codigo recibido. El contador se deriva del tiempo actual, asi que el codigo se renueva cada 30 o 60 segundos. Todo en tu navegador.
------
Validar un codigo
Como funciona TOTP
Un secreto compartido mas el reloj
TOTP se define en el RFC 6238 y es una capa fina sobre HOTP. Ambas partes guardan el mismo secreto, entregado normalmente una sola vez como codigo QR y almacenado en una app autenticadora. Para producir un codigo, cada lado toma la hora Unix actual, la divide por el tamano de paso (30 segundos por defecto) para obtener un contador, calcula HMAC-SHA1 de ese contador con el secreto y trunca el resultado al numero de digitos necesario.
Como el contador viene del reloj y no de un mensaje, no hace falta que viaje nada entre las dos partes despues del alta. El servidor no envia un reto y la app no necesita red: por eso las apps autenticadoras funcionan en modo avion.
Truncado y numero de digitos
La salida del HMAC son 20 bytes, muchos mas de los que necesita un codigo de 6 digitos. El truncado dinamico usa el nibble bajo del ultimo byte como desplazamiento, lee cuatro bytes desde ahi, enmascara el bit alto para evitar problemas de signo y toma ese numero modulo 10^digitos. Usar un desplazamiento variable en lugar de fijo impide que un atacante concentre el analisis en una porcion conocida del digest.
Seis digitos es el valor por defecto casi universal. Ocho digitos lo admiten la mayoria de apps y aportan unos dos digitos decimales mas de resistencia a la adivinacion, algo que importa mucho menos que la limitacion de intentos: un codigo de 6 digitos tiene una probabilidad de uno entre un millon por intento, asi que la defensa real es bloquear tras unos pocos fallos.
Deriva de reloj y repeticion
Los dispositivos se desvian. Los servidores suelen aceptar tambien el codigo de la ventana anterior y la siguiente ademas de la actual, lo que da una tolerancia de ±30 segundos. Ampliar esa ventana mas alla de uno o dos minutos aumenta de forma apreciable la superficie de ataque y suele ser senal de que hay que corregir el reloj del dispositivo.
Al desplegarlo conviene recordar dos propiedades. Un codigo sigue siendo valido durante toda su ventana, asi que un codigo interceptado puede repetirse dentro de ella salvo que el servidor marque los contadores usados como gastados. Y el secreto es simetrico: quien tenga la copia del lado servidor puede generar codigos validos para siempre, asi que necesita la misma proteccion que una base de datos de contrasenas: cifrado en reposo, nunca en logs, nunca en un repositorio git.
Preguntas frecuentes
¿Puede sustituir a mi aplicación de autenticación?
Es útil para pruebas y para recuperar un código cuando no tienes el móvil a mano, pero una pestaña del navegador no es un lugar seguro para guardar un secreto compartido de larga vida.
¿Por qué se rechaza mi código?
Casi siempre por desfase del reloj. TOTP deriva el código de la hora UNIX actual, así que un dispositivo desfasado más de un intervalo de 30 segundos genera un código que el servidor ya ha superado.
¿Qué representa el secreto en Base32?
Es la clave compartida que poseen ambas partes. Se usa Base32 porque no distingue mayúsculas y evita caracteres ambiguos, lo que facilita teclearla o codificarla en un QR.
¿Por qué los códigos tienen seis dígitos?
RFC 6238 trunca el HMAC a un valor de 31 bits y lo reduce módulo 10^6. Seis dígitos equilibran la usabilidad con una probabilidad de acierto de uno entre un millón por intento, que la limitación de tasa reduce todavía más.
¿Cuál es la diferencia entre TOTP y HOTP?
TOTP cuenta intervalos de 30 segundos; HOTP cuenta eventos y solo avanza cuando se usa un código. TOTP necesita relojes sincronizados y HOTP contadores sincronizados.
¿Se puede usar el mismo código dos veces?
No debería. Un código sigue siendo válido durante todo su intervalo, así que el servidor debe registrar qué intervalo ha consumido ya cada usuario y rechazar la repetición.