La guía completa del TOTP en equipo

Cómo funciona el TOTP, qué propiedades del algoritmo causan todos los problemas de las cuentas compartidas, y qué debe montar un equipo.

TOTP toma dos entradas y produce una salida. Las entradas son un secreto compartido y la hora actual; la salida es un código de seis cifras que cualquiera que guarde el mismo secreto puede calcular. No hay ninguna llamada de red, ningún registro por dispositivo, y ningún rastro en el servidor del dispositivo que generó un código.

Todas las dificultades que un equipo encuentra con la 2FA en cuentas compartidas se derivan de esa frase. Esta guía explica el mecanismo y después lo que implica para un equipo de más de una persona.

¿Qué es el TOTP?

TOTP está especificado por la RFC 6238. Es una capa fina por encima de HOTP (RFC 4226), que genera un código a partir de un secreto y un contador. HOTP incrementa el contador en cada uso; TOTP sustituye el contador por la hora actual dividida en pasos fijos, para que los dos lados lleguen al mismo valor sin comunicarse.

¿Cómo funciona el TOTP?

Una generación se parece a esto:

counter = floor(unix_time / period)        # el periodo suele ser de 30 segundos
digest  = hmac_sha1(secret, counter)       # 20 bytes
offset  = digest[-1] & 0x0F                # truncamiento dinámico
number  = int_from(digest[offset:offset+4]) & 0x7FFFFFFF
code    = number % 10 ** digits            # completado con ceros, 6 cifras en general

Cuatro parámetros están en juego: el secreto, el periodo (30 segundos por defecto), el número de cifras (6) y el algoritmo (SHA-1 en la práctica). La aplicación de autenticación de un teléfono hace exactamente lo anterior, sin conexión. El servidor hace lo mismo y compara.

Dos consecuencias merecen decirse claramente, porque ahí empiezan la mayoría de los malentendidos:

  • Nada en un código identifica su origen. El servidor ve seis cifras que coinciden, no qué dispositivo ni qué persona las generó.
  • No hay ningún estado que revocar. Inscribir un dispositivo no es un registro, es una copia del secreto. Nada en la cuenta deja constancia de ello.

El secreto es la cuenta

El secreto suele tener de 16 a 32 caracteres base32. No caduca, no está ligado a ningún dispositivo, y el protocolo no tiene ninguna noción de su rotación.

Cuando escaneas un código QR de configuración, lees un URI en el formato publicado con el nombre de Key URI Format:

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

Esa cadena es la credencial entera. El código QR es una foto de ella. Lo que significa que una captura de la pantalla de inscripción no es una comodidad. Es el segundo factor, en una forma que se reenvía, se respalda y se indexa.

De ahí se derivan las propiedades que vuelven incómoda la 2FA compartida:

  1. La posesión equivale a acceso permanente. Quien tenga el secreto puede generar todos los códigos futuros, en cualquier dispositivo, para siempre.
  2. Las copias son invisibles. Ninguna página de seguridad te dirá jamás cuántas existen.
  3. Revocar significa recuperarlo todo. La única forma de invalidar una copia es desactivar la 2FA de la cuenta y reconfigurarla, para todo el mundo.

La inscripción, paso a paso

Lo que ocurre durante la configuración explica por qué algunas decisiones posteriores son irreversibles.

  1. El proveedor genera el secreto. Se crea en el servidor, se registra en tu cuenta, y no vuelve a cambiar a menos que se desactive la 2FA.
  2. Se presenta una vez, en forma de código QR y normalmente en forma de cadena base32 detrás de un enlace de «¿no puedes escanear?». Es el único momento en que la credencial se muestra a un humano.
  3. Tu cliente lo almacena. Una aplicación de autenticación lo escribe en el dispositivo; una caja fuerte de equipo lo escribe en su propio almacenamiento cifrado. Ambas hacen lo mismo: guardar una copia.
  4. Envías un código para confirmar. Eso prueba que la copia funciona. No es un registro del dispositivo: nada relativo a tu teléfono se envía a ninguna parte.
  5. El proveedor entrega códigos de recuperación, normalmente en ese momento, y normalmente una sola vez.

El paso 2 es todo lo que está en juego. Lo que vea esa pantalla guarda el segundo factor de la cuenta a partir de entonces, y el paso 4 no da ninguna indicación de cuántas cosas lo han visto. Por eso «vamos a hacer una captura por ahora» es una decisión sin fecha de caducidad, y por eso la buena pregunta durante la configuración no es quién lo escanea, sino dónde va a vivir la única copia.

Por qué existe la ventana de treinta segundos

Los dos lados deben ponerse de acuerdo sobre el contador sin hablarse: así que se ponen de acuerdo sobre la hora. Un paso de treinta segundos es el compromiso: lo bastante largo para teclear un código, lo bastante corto para que un código capturado ya no valga nada poco después.

Los verificadores suelen aceptar también el paso inmediatamente anterior, y a veces el siguiente, para absorber el tiempo de escritura y los pequeños desfases de reloj. Por eso un código a menudo sigue funcionando unos segundos después de que la cuenta atrás vuelva a cero.

También significa que los relojes cuentan. Un dispositivo cuyo reloj tenga un minuto de desfase calcula los códigos de un paso que el servidor ya ha dejado atrás, y todos los códigos se rechazan. Cuando alguien informa de que los códigos han dejado de funcionar, un reloj no sincronizado es lo primero que hay que comprobar, antes de suponer que el secreto es falso. Todo lo que genere códigos para un equipo necesita un reloj sincronizado como exigencia estricta, no como comodidad.

Cómo funciona la verificación, y por qué un código solo debería servir una vez

Al otro lado, el verificador calcula el código esperado para el paso actual y compara. Tres detalles de esa comparación importan a quien gestiona cuentas compartidas.

La ventana de aceptación es un compromiso deliberado. Cada paso adicional aceptado por un servidor alarga el tiempo durante el cual un código capturado sigue siendo utilizable. Un paso hacia atrás es normal; las ventanas amplias señalan un servicio que enmascara problemas de reloj.

Un código debería ser de un solo uso. La RFC 6238 dice explícitamente que una segunda autenticación con el mismo paso de tiempo debería rechazarse, y las buenas implementaciones siguen el último paso usado por cuenta. El efecto práctico para un equipo: dos personas que se conectan en los mismos treinta segundos pueden ver rechazado el segundo intento aunque el código mostrado sea correcto. Esperar al código siguiente es el remedio, y no es un fallo.

Los intentos deberían estar limitados. Seis cifras son un millón de posibilidades, lo que solo resiste a la fuerza bruta si el servidor limita los intentos. Esa protección vive enteramente en el lado del proveedor; nada de lo que hagas con el secreto la mejora.

Ninguno de estos puntos se configura del lado de un equipo, pero los tres explican síntomas que, de otro modo, parecen una configuración rota: un código que funciona con retraso, un código que funciona para un compañero y no para el siguiente, un inicio de sesión que empieza a rechazar códigos correctos tras una ráfaga de intentos.

¿Es seguro el TOTP? Contra qué protege y contra qué no

Defiende bien contra las contraseñas reutilizadas, el relleno de credenciales salidas de filtraciones, y una contraseña filtrada de forma aislada. Un atacante que solo tenga la contraseña no puede conectarse.

No defiende contra una retransmisión en tiempo real: una página de inicio de sesión falsa convincente que pide el código y lo transmite dentro de su ventana de validez. Los códigos TOTP son phishables por diseño, puesto que el usuario puede leerlos. Tampoco hace nada contra un programa malicioso en el dispositivo que los genera, una cookie de sesión robada, o un secreto copiado.

Este último punto es la brecha que afecta a los equipos. Todas las demás amenazas de la lista las tratan los ajustes de seguridad de la propia cuenta. Un secreto copiado solo lo trata la forma en que tu equipo lo custodia, algo que el proveedor no puede ver ni ayudar.

Dónde los equipos rompen el TOTP

Por daño creciente:

  • Una persona se queda con la aplicación. Ningún secreto se copia, pero la cuenta depende ahora de la disponibilidad de un ser humano.
  • Un teléfono dedicado en un cajón. Muy bien en la oficina, inútil a distancia, y no registra nada.
  • El secreto junto a la contraseña en una caja fuerte compartida. Práctico, y reúne los dos factores en un solo contenedor.
  • El código QR publicado en un canal. Distribución permanente e incontable de la credencial.

Los dilemas de cada uno, y cómo elegir, son el tema de las mejores formas de gestionar la 2FA de una cuenta compartida y, tipo de cuenta por tipo de cuenta, de la 2FA de una cuenta compartida: ¿cómo debería abordarla un equipo?.

Lo que exige una instalación TOTP a la medida de un equipo

Una instalación que sobrevive a más de una persona necesita seis cosas, sea cual sea la herramienta elegida. Es la lista que hay que comprobar antes de elegir.

Una custodia única del secreto. Un solo sitio lo guarda, introducido una vez, por la persona que administra la cuenta. Todo lo demás consume códigos.

Una distribución de los códigos sin distribución del secreto. Quienes deban conectarse obtienen el código vigente y la cuenta atrás, y no pueden reconstituir el secreto a partir de lo que ven.

Una autorización por persona y por cuenta. No por caja fuerte. Quien publica en el perfil social no tiene ninguna razón para generar códigos para el proveedor de pago.

Un rastro de las consultas de códigos. El registro del proveedor mostrará la cuenta compartida, no la persona. Un registro de quién pidió un código es lo único que reduce un incidente a un nombre y una marca de tiempo.

Un reloj sincronizado en todos los sitios donde se generan códigos, por la razón dada más arriba.

Un camino de recuperación probado. Es la parte que los equipos descubren en el peor momento.

Copias de seguridad y recuperación

Dos cosas distintas deben ser recuperables, y no deberían vivir ni en el mismo sitio la una que la otra, ni en la cuenta que protegen.

El secreto, porque perderlo obliga a restablecer la 2FA de la cuenta. Su ubicación debería estar anotada, y ser alcanzable por más de un administrador.

Los códigos de recuperación del proveedor, que son repliegues de un solo uso entregados en la inscripción. Sirven para el día en que el secreto ha desaparecido, no para el acceso diario: son limitados, y nadie puede decir cuál ha consumido quién.

Guardar la única copia de un código de recuperación en la cuenta que recupera es un bucle que se cierra exactamente cuando lo necesitas abierto. Lo mismo para el secreto de la cuenta que guarda la caja fuerte que contiene tus secretos.

El camino de recuperación merece recorrerse una vez, a propósito, en una cuenta sin importancia: desactivar la 2FA con un código de recuperación, reconfigurarla, comprobar que todos los que necesitan los códigos siguen teniéndolos. Sin ese ensayo, descubrirás el procedimiento el día en que la cuenta ya es inaccesible.

Los parámetros que encontrarás de verdad

Los valores por defecto cubren la abrumadora mayoría: SHA-1, seis cifras, treinta segundos. El uso de SHA-1 aquí no es la debilidad que parece, puesto que HMAC-SHA1 no se ve afectado por los ataques por colisión que jubilaron a SHA-1 para las firmas. La RFC autoriza SHA-256 y SHA-512, pero el soporte de las aplicaciones es lo bastante desigual como para que los proveedores rara vez los usen.

Una minoría de servicios se aparta: ocho cifras, un periodo de sesenta segundos, o un alfabeto de código no numérico. La consecuencia práctica es una exigencia de almacenamiento. Lo que guarde un secreto debe guardar sus parámetros digits, period y algorithm al lado, sin lo cual los códigos de esas cuentas serán falsos de una manera que parece un secreto roto. Toda herramienta que solo acepte una cadena de secreto desnuda supone en silencio los valores por defecto.

Pequeño glosario

Merece la pena ponerse de acuerdo sobre esto dentro de un equipo, porque estas palabras se usan indistintamente y la gente acaba hablando de cosas distintas.

  • Secreto (o semilla): la cadena base32 de la que salen los códigos. Permanente.
  • Clave: casi siempre un sinónimo de secreto. A veces se designa así el Key URI, que es otra cosa.
  • Código (u OTP): las seis cifras. Válido un paso, de un solo uso.
  • Token: usado indistintamente para las seis cifras y, en un hardware dedicado, para el dispositivo que guarda el secreto. Precisa cuál.
  • HOTP: la misma construcción con un contador que se incrementa en cada uso.
  • Periodo / paso de tiempo: el intervalo de validez de un código, normalmente 30 segundos.
  • Deriva: el desfase entre dos relojes, que hace fallar los códigos.
  • Key URI / URI otpauth: la forma textual de la carga de inscripción; el código QR es su codificación visual.
  • Códigos de recuperación: repliegues de un solo uso proporcionados por el servicio, sin relación con TOTP.
  • Inscripción: la copia del secreto en un dispositivo. No un registro, pese a la impresión que da.

Dónde se sitúa Share Auth

Share Auth pone en práctica las seis exigencias anteriores para las cuentas que de verdad solo tienen un identificador. Los secretos se introducen una vez y se cifran en reposo, con digits, period y algorithm almacenados al lado; los miembros ven códigos y cuentas atrás en lugar de secretos; los permisos son por miembro; y cada consulta se escribe en un registro de accesos. Retirar a un miembro retira su acceso a todas las cuentas de golpe.

No es un sustituto del acceso por persona en las plataformas que lo ofrecen. Allí donde una herramienta pueda dar a cada compañero su propio identificador y su propio segundo factor, eso es estrictamente mejor que compartir nada.

Lista de comprobación

  • El secreto de cada cuenta compartida tiene un domicilio conocido, alcanzable por dos administradores.
  • Nadie necesita el secreto para obtener un código.
  • El acceso se concede por persona, por cuenta, y es retirable en una acción.
  • Las consultas de códigos se registran en el momento en que ocurren.
  • Los códigos de recuperación se guardan con el secreto, fuera de la cuenta que recuperan.
  • Los relojes están sincronizados en todos los sitios donde se generan códigos.
  • El camino de recuperación se ha probado una vez, a propósito.
  • Toda cuenta cuyo código QR se haya compartido alguna vez ha visto su 2FA restablecida.

Preguntas frecuentes

TOTP, de «time-based one-time password», es el algoritmo especificado por la RFC 6238 que convierte un secreto compartido y la hora actual en un código corto, seis cifras la mayoría de las veces, válido unos treinta segundos. La cuenta y la aplicación de autenticación guardan el mismo secreto: calculan, pues, el mismo código sin intercambiar nada.

Sigue leyendo · Cómo funciona TOTP