Saltar al contenido
nvíame
Capítulo 2 de 411 min10 oct 2026

Emite y verifica un OTP

Genera códigos con aleatoriedad criptográfica y verifícalos de una sola vez.

Emitir un OTP es generar un número aleatorio de 6 dígitos, guardarlo asociado al teléfono con una expiración y enviarlo. Verificar es comparar y, si coincide, invalidarlo.

Pruébalo

mx.otp.issue(phone) genera un código con crypto.getRandomValues y lo muestra como mensaje de sistema. mx.otp.verify(phone, code) devuelve true una sola vez: el código se consume al usarse.

// Emite y verifica un OTP
const phone = "+56987654321";

const code = mx.otp.issue(phone);
console.log("código emitido (en producción nunca lo registres):", code);

console.log("código erróneo →", mx.otp.verify(phone, "000000"));
console.log("código correcto →", mx.otp.verify(phone, code));
console.log("reutilizado →", mx.otp.verify(phone, code));

Guarda el hash, no el código

Guarda un hash del código (por ejemplo SHA-256 con el teléfono como sal) en lugar del código en texto plano. Si tu almacén se filtra, los códigos vigentes no quedan expuestos.

Almacenamiento del código
−store.set(phone, { code, exp: Date.now() + 300000 });
+const hash = await sha256(phone + ":" + code);
+store.set(phone, { hash, exp: Date.now() + 300000, attempts: 0 });
Mostrando: antes · haz clic para alternar

Observa en el playground que el código se elimina después de una verificación exitosa: un OTP es de un solo uso por definición. Si vuelves a llamar a verify con el mismo código, obtendrás false.

Se completa automáticamente al leer el 80%.

Comentarios (3)

Diego Fernández10 oct 2026

¿Por qué no usar `Math.random()` para el código?

Equipo nvíameAutor10 oct 2026

Porque no es criptográficamente seguro: su secuencia puede predecirse. Usa `crypto.getRandomValues` o `crypto.randomInt` en Node.

Sofía Castillo10 oct 2026

Lo apliqué en el proyecto del trabajo. La sección «Emite y verifica un OTP» me ahorró una discusión larga con el equipo: ahora tenemos un criterio compartido.

Valentina Muñoz10 oct 2026

¿Hay alguna diferencia importante si lo implemento en un servicio con varias instancias detrás de un balanceador?

Equipo nvíameAutor10 oct 2026

Sí: todo estado que hoy vive en memoria (contadores, sesiones, claves vistas) debe moverse a un almacén compartido con TTL, como Redis. Si no, cada instancia ve solo una parte de la historia.

Los comentarios se guardan solo en este navegador.