Seguridad

Generador de códigos TOTP de dos factores

Pega el secreto base32 que te dio un sitio —o el enlace otpauth:// completo— y aparece el código actual, junto con el que viene después y cuánto tiempo le queda al actual. El secreto vive solo en la página y en ningún otro lado; al recargar se olvida.

Solo base32. Los espacios y las minúsculas no son problema. Pega un enlace otpauth:// completo y los ajustes de al lado se completan solos.

------ Código actual
-- Segundos restantes
------ Código siguiente

El reloj de tu dispositivo decide el código. Si todos los códigos son rechazados, revisa el reloj antes de culpar al secreto.

Cómo salen seis dígitos de un secreto compartido

TOTP es una capa fina sobre HMAC. Tú y el servidor guardan el mismo secreto, normalmente 20 bytes aleatorios. Ambos lados toman el tiempo Unix actual, lo dividen por 30 y descartan el resto, lo que da un contador que cambia dos veces por minuto y es el mismo en las dos máquinas. Ese contador se escribe como ocho bytes y pasa por HMAC usando el secreto compartido como clave.

El resultado son 20 bytes, demasiados para escribirlos a mano. El último nibble del MAC se lee como un número del 0 al 15, y ese número se usa como desplazamiento dentro del propio MAC: se toman cuatro bytes desde ahí, se descarta el bit más alto y el resto de dividirlo por un millón da seis dígitos. Descartar el bit más alto no tiene nada que ver con la seguridad: existe para que las implementaciones que tratan el valor como con signo y las que lo tratan como sin signo den la misma respuesta.

La versión basada en contador es HOTP, definida en el RFC 4226; TOTP, en el RFC 6238, es la misma construcción con el tiempo como contador. Ese linaje explica por qué el truncamiento se ve tan raro: se diseñó en 2005 para poder implementarse en un token de hardware.

Por qué el secreto está en base32

Base32 usa de la A a la Z y los dígitos del 2 al 7. No hay 0, ni 1, ni 8, precisamente porque son los caracteres que la gente confunde con O, I y B al copiar una clave a mano. Además no distingue mayúsculas de minúsculas, cosa que base64 sí hace. El costo es el tamaño: base32 necesita 32 caracteres para llevar los 20 bytes que base64 mete en 27.

Si la herramienta de arriba rechaza un carácter, ese suele ser el problema: una O mayúscula escrita donde nunca hubo un cero, o una l minúscula haciendo de 1.

El reloj es la mitad del algoritmo

No se intercambia nada cuando escribes un código. El servidor calcula el mismo número por su cuenta, y eso solo funciona si los dos relojes coinciden. La mayoría de los servidores aceptan también el paso anterior y el siguiente además del actual, o sea una ventana de unos 90 segundos con el paso habitual de 30 segundos. Más allá de eso, los códigos simplemente son incorrectos.

Un dispositivo cuyo reloj se desvió unos minutos genera códigos que son rechazados en todas partes, lo que se parece exactamente a un secreto roto. Esta página no puede avisarte de que tu reloj está mal, porque nunca habla con un servidor: no hay nada con qué comparar.

Lo que un segundo factor no resuelve

TOTP acaba con el credential stuffing y la reutilización de contraseñas: una contraseña filtrada por sí sola ya no alcanza. No detiene el phishing. Un código escrito en una página falsa convincente vale 30 segundos para quien esté haciendo de intermediario con el sitio real, y los kits de phishing modernos hacen exactamente eso en tiempo real. Las passkeys y las llaves de seguridad resuelven esto de verdad porque atan el inicio de sesión al origen del sitio, algo que un número de seis dígitos copiado no puede hacer.

El otro punto débil es la semilla misma. El servidor tiene que guardarla en un formato que pueda leer, así que una filtración de la base de datos les entrega a los atacantes un generador de códigos permanente, no solo un hash de contraseña para romper por fuerza bruta.

Dónde se detiene esta herramienta

No puede leer un código QR. Aquí no hay acceso a la cámara ni decodificador de QR, así que necesitas la semilla en texto: casi todos los sitios la muestran detrás de un enlace del tipo "¿no puedes escanear el código?" junto a la imagen.

No hace HOTP. Los códigos basados en contador necesitan un estado que sobreviva entre usos, y esta página, deliberadamente, no guarda nada.

Algunos servicios usan un TOTP modificado que nunca va a coincidir: los códigos de cinco caracteres de Steam son el ejemplo más conocido, ya que mapean el mismo número truncado a un alfabeto propio en lugar de a dígitos.

Los campos de dígitos, paso y algoritmo existen porque el formato otpauth los permite, pero varias aplicaciones de autenticación populares ignoran esos parámetros por completo y asumen SHA-1, seis dígitos y treinta segundos. Si un enlace dice SHA-256 y todos los códigos son rechazados, prueba con SHA-1 antes de concluir que el secreto está mal.

Por último, lo evidente. Una herramienta que tiene tu semilla 2FA puede generar tus códigos para siempre, y pegar una semilla activa en cualquier página web es una decisión que conviene tomar a conciencia. Aquí nada se escribe en el almacenamiento, ni se envía a ningún lado, ni se conserva tras recargar, pero esto está hecho para probar una implementación, confirmar que una semilla respaldada sigue funcionando o entrar una vez cuando no tienes el teléfono. No es una aplicación de autenticación.

Preguntas frecuentes

¿Mi secreto se envía a algún lado?

No. La página son archivos estáticos sin ningún servidor detrás, el código se calcula con la API crypto del navegador, y el secreto no se escribe en el almacenamiento local, ni en cookies, ni en la URL. Recarga la página y desaparece.

¿Por qué rechazan mi código aunque la herramienta muestre uno?

Tres causas habituales: un reloj del dispositivo desviado más de un minuto, un sitio que espera SHA-1 mientras el enlace pedía SHA-256, o un secreto copiado al que le falta un carácter. Prueba primero el mismo secreto con SHA-1, seis dígitos y un paso de 30 segundos.

¿Puedo usar esto en lugar de una aplicación de autenticación?

Puedes, y es un retroceso. Una aplicación guarda la semilla en el almacenamiento seguro del teléfono; una pestaña del navegador la deja en el portapapeles y en tu historial de páginas. Usa esto para probar una implementación o para recuperar el acceso, y mantén tu segundo factor de todos los días en una aplicación adecuada o en una llave de hardware.

¿Qué hago con un enlace otpauth://?

Pega el enlace entero en el campo del secreto. Se extrae el secreto y los ajustes de dígitos, paso y algoritmo se completan con los parámetros del enlace cuando están presentes.

¿Por qué no escanea el código QR?

Decodificar una imagen QR necesita acceso a la cámara o una biblioteca de decodificación, y ninguna de las dos cosas cabe en una herramienta tan pequeña. Todo sitio que muestra un código QR también muestra la semilla en texto para quien la escribe en una aplicación de escritorio: usa esa.

Última actualización 19 de septiembre de 2026