// lección (ejemplo) · nviaotp.me

TOTP: del secreto compartido al código verificable

Lección real con diagrama y ejercicio reproducible. Comprende el flujo completo de un código de un solo uso basado en tiempo según RFC 6238, sin salir del navegador y sin invocar redes productivas.

Lección verificable · Diagrama SVG inline · Ejercicio reproducible · Sin cifras inventadas · Español formal

nviaOTP—:—

Ejemplo TOTP

Secreto base32 de ejemplo común en demostraciones de TOTP

—
RFC 6238

Ilustración · Generado localmente · Válido 30 s

¿Qué vas a aprender?

Al terminar esta lección podrás explicar el flujo TOTP de extremo a extremo y reproducir un ejercicio de verificación con un diagrama claro y un paso a paso verificable.

Secreto compartido

Por qué se usa una clave base32 y cómo se intercambia de forma segura entre el servidor y el cliente.

RFC 6238

Algoritmo HMAC

El papel del HMAC-SHA1 para convertir el contador de tiempo en un valor íntegro y autenticado.

Progreso local

Ventana de validez

Por qué 30 segundos y cómo el servidor tolera desfases sin romper la seguridad.

NO MEDIDO

Flujo TOTP de extremo a extremo

Diagrama simplificado, sobrio y verificable. No se muestran componentes propietarios; solo el patrón definido por el RFC.

Figura 1 — Generación y verificación

Flujo TOTP Diagrama del flujo TOTP: secreto compartido y timestamp alimentan HMAC-SHA1, se aplica truncado dinámico y se obtiene un código de 6 dígitos. El servidor calcula el mismo código y compara. Secreto base32 Timestamp T / 30 s HMAC-SHA1 RFC 2104 Truncado dinámico Código 6 dígitos Servidor almacena secreto Calcula mismo código Compara códigos Si coinciden → autenticado envío

Figura 1 — Flujo TOTP según RFC 6238. La línea punteada representa el envío del código por el usuario al servidor. Todos los pasos de cálculo se realizan localmente en esta lección.

El flujo se compone de cinco etapas determinísticas. Primero, el servidor y el cliente comparten un secreto codificado en base32. Segundo, se calcula un contador dividiendo el tiempo Unix entre el período (30 s). Tercero, se aplica HMAC-SHA1 sobre el contador usando el secreto como clave.

Cuarto, se aplica el truncado dinámico definido por el RFC: se toma el último byte del HMAC, se extraen los cuatro bits menos significativos como desplazamiento, y se leen cuatro bytes a partir de esa posición, descartando el bit de signo. Quinto, se aplica módulo 10dígitos para obtener el código final.

Ejercicio real reproducible

Implementación real de TOTP usando Web Crypto API (SubtleCrypto). El cálculo se ejecuta en tu navegador sin enviar datos a la red. Compara el resultado con cualquier aplicación autenticadora estándar.

Paso a paso

1. Secreto compartido de ejemplo

Secreto base32: JBSWY3DPEHPK3PXP. Este es un secreto de ejemplo común en demostraciones de TOTP.

2. Calcular el código TOTP

La siguiente función implementa TOTP según RFC 6238 usando HMAC-SHA1. Se ejecuta localmente en el navegador mediante la Web Crypto API.

totp.js — implementación realWeb Crypto API
// Decodifica base32 (RFC 4648)
// Versión alineada con la implementación ejecutada en esta página
function decodeBase32(str) {
  const alphabet = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ234567';
  let bits = '';
  for (const ch of str.toUpperCase()) {
    const v = alphabet.indexOf(ch);
    if (v < 0) continue;
    bits += v.toString(2).padStart(5, '0');
  }
  const out = new Uint8Array(Math.floor(bits.length / 8));
  for (let i = 0; i < out.length; i++) {
    out[i] = parseInt(bits.slice(i * 8, i * 8 + 8), 2);
  }
  return out;
}

// Genera TOTP según RFC 6238 (HMAC-SHA1, 6 dígitos, paso 30 s)
async function generarTOTP(secretBase32, timestamp = Date.now(), digits = 6, period = 30) {
  const keyBytes = decodeBase32(secretBase32);
  const counter = Math.floor(timestamp / 1000 / period);

  const buf = new ArrayBuffer(8);
  const view = new DataView(buf);
  view.setUint32(0, Math.floor(counter / 0x100000000), false);
  view.setUint32(4, counter & 0xffffffff, false);

  const key = await crypto.subtle.importKey(
    'raw', keyBytes, { name: 'HMAC', hash: 'SHA-1' }, false, ['sign']
  );
  const sig = new Uint8Array(await crypto.subtle.sign('HMAC', key, buf));

  const offset = sig[sig.length - 1] & 0x0f;
  const code = ((sig[offset] & 0x7f) << 24) |
               ((sig[offset + 1] & 0xff) << 16) |
               ((sig[offset + 2] & 0xff) << 8) |
               (sig[offset + 3] & 0xff);

  return String(code % Math.pow(10, digits)).padStart(digits, '0');
}
3. Resultado en vivo

Pulsa el botón para calcular el código TOTP del secreto de ejemplo en este momento. El código se actualiza cada 30 segundos respetando la ventana del RFC.

Código TOTP actual
—
Requiere JavaScript
4. Verificar la ventana de tiempo

El código cambia cada 30 segundos. Si tu cliente y servidor están desincronizados, se permite un desfase de ±1 paso (configurable). En esta lección el cálculo es local, por lo que la verificación es exacta.

Nota: El ejercicio es educativo. Todo el cálculo se ejecuta localmente; no se envían secretos, códigos ni datos de tiempo a un servidor.

Comprobación y lectura responsable

Contrasta la implementación con un vector de prueba publicado en RFC 6238 y separa las propiedades del algoritmo de las medidas que un servicio productivo debe configurar por separado.

RFC 6238 Cálculo local Ejemplo educativo
Aclaración técnica: el secreto Base32 JBSWY3DPEHPK3PXP es un secreto de ejemplo común en demostraciones de TOTP. No corresponde a un vector oficial del RFC 6238 y no debe utilizarse como secreto productivo.

Vector de referencia SHA-1

RFC 6238 define la semilla ASCII de 20 bytes 12345678901234567890 y el instante Unix 59. Su Base32 es GEZDGNBVGY3TQOJQGEZDGNBVGY3TQOJQ.

Resultado esperado: 94287082.

Límites del algoritmo

TOTP no resuelve por sí solo la distribución segura del secreto, la precisión del reloj, la protección contra reintentos, la gestión de sesiones ni la respuesta ante fraude.

Esos controles corresponden a la arquitectura del producto y a una política configurable.

Comprobación reproducible

1. Ejecutar el vector oficial

Selecciona el botón anterior. La página calculará HMAC-SHA1, aplicará truncado dinámico y devolverá un código de ocho dígitos para el instante fijo T = 59. El resultado debe coincidir con 94287082.

Resultado calculado
—
Pendiente de comprobación
2. Comprender la ventana temporal

TOTP deriva el contador de la expresión floor((UnixTime − T0) / X). En este ejemplo, T0 = 0 y X = 30 s. Un verificador puede comparar el código del intervalo actual y los intervalos adyacentes para tolerar desfases de reloj, pero esa política debe limitarse y documentarse.

3. Preguntas de comprensión
¿Qué algoritmo firma el contador?

HMAC-SHA-1. RFC 6238 también incluye vectores de prueba para HMAC-SHA-256 y HMAC-SHA-512; la elección productiva debe responder a la política criptográfica configurada.

¿Qué cambia el código?

Cambia el contador derivado del tiempo. Para una misma clave, un timestamp fijo y parámetros fijos, el algoritmo produce un resultado determinístico.

¿Basta con compartir un secreto?

No. La generación del código no sustituye la protección del secreto, la gestión de autenticadores, la sincronización del reloj, el control de reintentos, la protección de sesiones ni la evaluación de riesgo.

Uso seguro: no registres el secreto de ejemplo en una cuenta real, no lo reutilices en otro sistema y no lo trates como una credencial de producción. Los vectores públicos solo sirven para pruebas.

Siguientes pasos

Continúa con el laboratorio interactivo o revisa otras lecciones del catálogo. Las políticas de seguridad, observabilidad y cumplimiento deben documentarse para cada despliegue.

Laboratorio RFC 6238

Practica generación local, comparación de intervalos y caducidad del código en un entorno simulado.

Catálogo de cursos

Explora lecciones sobre HOTP, rate limiting, MFA y superficie de ataque dentro del mapa formativo.

// continuar hacia la plataforma

De aprender a construir a integrar capacidades de producción

Mobiconnect ofrece capacidades de Business API e IA sobre Open Telco, OpenAPI, CAMARA y GSMA Open Gateway. El acceso y el cobro mediante Entitlements se aplican como política configurable.

De aprender a construir