Depurador de códigos TOTP / 2FA

Genera y depura códigos TOTP / 2FA: la derivación RFC 6238 completa, verificación con ventana de deriva y análisis de otpauth:// — todo en tu navegador.

Tiempo

Introduce un secreto para ver un código.

otpauth:// URI para esta configuración
otpauth://totp/user%40example.com?secret=JBSWY3DPEHPK3PXP&algorithm=SHA1&digits=6&period=30

Qué son realmente los seis dígitos

Un código TOTP — el número que una app de autenticación renueva cada treinta segundos — no es aleatorio ni se guarda en ningún sitio. Se calcula, tanto en tu teléfono como en el servidor, a partir de dos cosas que ya comparten: un secreto configurado una vez al activar la autenticación de dos factores, y la hora actual. Como ambos lados pueden calcularlo de forma independiente, nada tiene que viajar entre ellos al iniciar sesión; el servidor simplemente ejecuta el mismo cálculo y comprueba que su respuesta coincide con la tuya.

TOTP (RFC 6238) es una fina capa sobre un esquema más antiguo, HOTP (RFC 4226). HOTP convierte un secreto y un contador en un código; TOTP es simplemente HOTP con el contador puesto al número de pasos de tiempo desde la época Unix. Esa es toda la idea: divide la hora Unix actual entre la longitud del paso (30 segundos por defecto) y pasa el resultado a HOTP. Esta herramienta muestra cada paso de ese cálculo, porque cuando un código no verifica, la respuesta casi siempre está visible en algún punto de la derivación.

La derivación, paso a paso

Cinco pasos llevan el secreto y la hora hasta los dígitos que escribes. La herramienta imprime cada uno para que puedas comparar con tu propia implementación:

  • El contador. Toma la hora Unix en segundos, resta T0 (0 en todo despliegue real), divide entre el periodo y redondea hacia abajo. Con pasos de 30 segundos, cualquier momento en el mismo medio minuto da el mismo contador, por eso un código dura lo que dura.
  • El HMAC. Escribe el contador como 8 bytes big-endian y calcula HMAC(secreto, contador) con el hash elegido — SHA-1 para casi todas las apps. Eso produce un resumen de 20 bytes para SHA-1 (32 para SHA-256, 64 para SHA-512).
  • El desplazamiento. Toma los cuatro bits bajos del último byte del resumen. Es un número de 0 a 15, y dice dónde leer en el resumen — truncamiento dinámico, para que el mismo secreto no use siempre los mismos bytes.
  • El valor de 31 bits. Lee cuatro bytes a partir del desplazamiento y enmascara el bit superior (para evitar confusiones de signo). Queda un entero de 31 bits.
  • El código. Toma ese entero módulo 10^dígitos y rellena con ceros a la izquierda. Seis dígitos es la elección casi universal; siete y ocho existen y están permitidos.

El enmascarado del bit superior y el módulo son los únicos pasos con pérdida: muchos resúmenes distintos mapean a los mismos seis dígitos, y está bien, porque el código solo tiene que ser difícil de adivinar en los treinta segundos que vive, no único para siempre.

Por qué un código no coincide — las tres causas habituales

Una discrepancia de TOTP nunca viene con un mensaje de error; el código simplemente es incorrecto. En la práctica casi siempre es una de tres cosas, y los paneles aquí están dispuestos para distinguirlas:

  • El secreto se leyó en el formato equivocado. Un secreto de autenticador es Base32, pero los mismos caracteres leídos como hex — o un secreto que era hex leído como Base32 — producen bytes completamente distintos y un código completamente distinto. Cambia el selector de formato y ve cuál da el código que esperas.
  • Un parámetro difiere. El valor por defecto abrumador es HMAC-SHA-1, 6 dígitos, un periodo de 30 segundos. Un servidor que use SHA-256, u 8 dígitos, o un paso de 60 segundos, discrepará con una app dejada en los valores por defecto. El otpauth:// URI lleva los tres, por eso escanear un QR los acierta y escribir un secreto a mano a menudo no.
  • Los relojes se han desviado. TOTP supone que ambos lados coinciden en la hora. Si el reloj de un teléfono adelanta un minuto, su código va un minuto por delante del servidor. Para eso está la ventana de deriva: verificar un código contra los pasos a ambos lados del ahora dice no solo si coincide sino cuánto se desvía el reloj.

RFC 6238 recomienda una ventana de validación de como mucho un paso a cada lado — suficiente para absorber el desfase de reloj habitual y la carrera del momento de renovación, sin ampliar el espacio de conjetura más de lo necesario. Esta herramienta usa ±1 por defecto y te deja ampliarla al depurar.

Secretos, Base32 y el otpauth:// URI

El secreto se comparte una vez, en la configuración, y todo lo demás se deriva de él. Las apps de autenticación lo codifican en Base32 (RFC 4648) — el alfabeto A–Z y 2–7, que evita los caracteres fáciles de confundir y sobrevive a imprimirse bajo un QR. Esta herramienta lee Base32 por defecto, ignorando los espacios que las apps añaden para legibilidad y las mayúsculas, y también acepta hex para que puedas reproducir los vectores de prueba de RFC 6238, cuyos secretos se dan como bytes en bruto.

El código QR que escaneas en la configuración tampoco es magia: codifica un otpauth:// URI en texto plano que lleva el secreto y todos los parámetros. Pega uno aquí para rellenar los campos, o construye uno desde los campos para mover una configuración entre apps:

otpauth://totp/GitHub:[email protected]?secret=JBSWY3DPEHPK3PXP&issuer=GitHub&algorithm=SHA1&digits=6&period=30

Solo se acepta el tipo totp. Un otpauth://hotp URI lleva un contador en lugar de un periodo, y tratarlo como TOTP produciría códigos incorrectos en silencio — así que se rechaza en vez de adivinar.

Algoritmo, dígitos y periodo

RFC 6238 permite HMAC-SHA-1, SHA-256 o SHA-512, de seis a ocho dígitos, y cualquier longitud de paso. En la práctica el mundo se asentó en SHA-1, seis dígitos y treinta segundos, y la mayoría de las apps solo implementan esa combinación — así que un servidor que elija otra cosa tiene que esperar que la app del usuario le siga, y muchas no lo hacen. La elección segura para la interoperabilidad es la aburrida.

Vale la pena abordar la cuestión de SHA-1 directamente, porque la herramienta de hash de este sitio marca SHA-1 como roto. Ambas afirmaciones son ciertas. SHA-1 es inservible para firmas digitales porque los atacantes pueden fabricar colisiones — dos documentos con el mismo hash. TOTP no depende de esa propiedad: su seguridad viene de la clave secreta dentro del HMAC, no de que el hash resista colisiones, y HMAC-SHA-1 sigue siendo sólido. Usar SHA-256 aquí es defendible pero aporta poco, y cuesta interoperabilidad con apps que solo hacen SHA-1.

Qué protege y qué no protege esta herramienta

Todo aquí se ejecuta en tu navegador. El HMAC se calcula con la Web Crypto API en tu propio dispositivo, el mismo primitivo que usan las herramientas de hash y HMAC, y nada de lo que escribes — secreto, código o otpauth URI — se sube, se guarda ni se registra. Es una propiedad de que el código sea del lado del cliente, no una promesa que tengas que creer.

Dicho esto, un secreto TOTP es un segundo factor: cualquiera que lo tenga puede generar tus códigos. Pegar un secreto de producción en cualquier página web — incluida esta — lo pone en el portapapeles y posiblemente en el historial del navegador, así que trátalo con el mismo cuidado que una contraseña, y prefiere un secreto desechable o de prueba cuando solo necesites entender el mecanismo. La herramienta existe para depurar y aprender, no para ser donde vive tu segundo factor real.

Preguntas frecuentes

¿Se envía mi secreto a un servidor?
No. El código se calcula en tu navegador con la Web Crypto API, y nada de lo que escribes se sube ni se registra. Como un secreto TOTP es un segundo factor, ten cuidado igualmente al pegar uno de producción — puede pasar por el portapapeles y el historial del navegador como cualquier texto.
¿Por qué mi código no coincide con mi app de autenticación?
Casi siempre una de tres cosas: el secreto se leyó en el formato equivocado (Base32 vs hex), un parámetro difiere de los valores por defecto (la mayoría de apps son SHA-1, 6 dígitos, periodo de 30 segundos), o el reloj del dispositivo se desvió. El panel de derivación aísla las dos primeras, y verificar con una ventana de deriva ± revela la tercera.
¿Cuál es la diferencia entre TOTP y HOTP?
HOTP (RFC 4226) calcula un código a partir de un secreto y un contador que se incrementa con cada uso. TOTP (RFC 6238) es la misma construcción con el contador puesto al número de pasos de tiempo desde la época Unix, así que el código cambia con el reloj en vez de con una pulsación. TOTP es lo que usan las apps de autenticación.
¿Por qué SHA-1 es el valor por defecto si está roto en otros sitios?
SHA-1 está roto para firmas porque se pueden construir colisiones, pero HMAC — sobre el que se construye TOTP — no depende de la resistencia a colisiones; su seguridad reside en la clave secreta. HMAC-SHA-1 es sólido, y es el único algoritmo que implementan muchas apps de autenticación, así que es el valor por defecto tanto seguro como compatible.
¿Puedo fijar el código a una hora concreta?
Sí. Cambia la hora de en vivo a fijada e introduce una marca de tiempo Unix. El código entonces se queda estático, que es como se reproduce un vector de prueba publicado — RFC 6238 da valores en horas como 59 y 1111111109 — o se comprueba qué código era válido en un momento pasado.
¿Qué tamaño debe tener la ventana de deriva?
RFC 6238 recomienda como mucho un paso a cada lado, que es lo que usa esta herramienta por defecto. Una ventana más amplia tolera un reloj más desviado pero también amplía el conjunto de códigos que un servidor aceptaría, así que es un compromiso; ±1 es el equilibrio estándar.
¿Para qué sirven los dígitos y el periodo?
Los dígitos son cuántas cifras tiene el código — seis casi en todas partes, siete u ocho donde un servicio quiere algo más de fuerza. El periodo es cuántos segundos permanece válido un código, treinta por defecto. Ambos van en el otpauth:// URI, y ambos tienen que coincidir en los dos lados o los códigos no concordarán.