29. Aplicaciones de la aritmética modular en criptografía

La aritmética modular permite construir transformaciones fáciles de calcular pero difíciles de invertir sin una clave. Esta idea sostiene el cifrado de clave pública, el intercambio de claves, las firmas digitales y numerosas verificaciones de seguridad.

29.1 Introducción

La criptografía protege información frente a personas no autorizadas. Para lograrlo necesita operaciones que sean eficientes para quienes poseen una clave, pero que no revelen esa clave a partir de los datos públicos.

Las congruencias, las potencias modulares, los números coprimos y los inversos modulares que estudiamos en los temas anteriores forman el lenguaje matemático de varios sistemas criptográficos clásicos y modernos.

29.2 Objetivos de la criptografía

La seguridad de un sistema no se limita a ocultar un mensaje. Según el caso, se buscan una o varias propiedades:

Confidencialidad: solo destinatarios autorizados leen el dato.
Integridad: se detectan alteraciones.
Autenticidad: se identifica el origen del dato.
No repudio: el emisor no puede negar de forma creíble una firma válida.

El cifrado se centra en la confidencialidad. Los hashes, los códigos de autenticación y las firmas digitales cubren otras necesidades y no son intercambiables.

29.3 El papel del módulo

Trabajar módulo m mantiene los resultados en un conjunto finito de residuos. Así, una potencia muy grande se representa por un número entre 0 y m - 1 sin perder la información relevante para el algoritmo.

7100 puede tener decenas de dígitos.
Pero 7100 mod 13 es un único residuo entre 0 y 12.

La reducción modular permite calcular y transmitir valores manejables.

La criptografía no depende de que el módulo sea secreto. En los sistemas bien diseñados, los parámetros públicos pueden conocerse; la seguridad descansa en una clave privada y en problemas matemáticos difíciles.

29.4 Potenciación modular eficiente

Elevar una base a un exponente grande y reducir módulo m es una operación central. La exponenciación por cuadrados procesa los bits del exponente y reduce después de cada multiplicación.

function moduloBigInt(a, m) {
  if (m <= 0n) throw new Error("el módulo debe ser positivo");
  return ((a % m) + m) % m;
}

function potenciaModBigInt(base, exponente, m) {
  if (exponente < 0n || m <= 0n) throw new Error("argumentos inválidos");

  let resultado = 1n;
  let factor = moduloBigInt(base, m);

  while (exponente > 0n) {
    if (exponente % 2n === 1n) resultado = (resultado * factor) % m;
    factor = (factor * factor) % m;
    exponente /= 2n;
  }
  return resultado;
}

console.log(potenciaModBigInt(7n, 100n, 13n)); // 9n

Usamos BigInt porque los parámetros criptográficos exceden ampliamente el rango de enteros seguros de Number. El algoritmo mostrado ilustra la matemática; no constituye por sí solo una implementación criptográfica de producción.

29.5 Funciones fáciles de calcular y difíciles de invertir

Una función criptográfica suele ser fácil de aplicar en una dirección y difícil de invertir sin información adicional. Por ejemplo, calcular una potencia modular es eficiente; recuperar un exponente desconocido a partir de la base, el módulo y el resultado puede ser muy difícil en grupos elegidos adecuadamente.

Dato público: g, p y A = ga mod p.
Secreto: el exponente a.

Calcular A desde a es rápido.
Intentar recuperar a desde A puede ser difícil.

La dificultad depende de la estructura matemática y del tamaño de los parámetros. Ejemplos pequeños sirven para aprender, pero son completamente vulnerables a una búsqueda exhaustiva.

29.6 Números primos y coprimalidad

Los números primos aparecen porque, módulo un primo p, todo residuo distinto de cero tiene inverso multiplicativo. Esto hace que las operaciones no nulas se comporten de forma especialmente regular.

Módulo 7, los residuos no nulos son 1, 2, 3, 4, 5 y 6.
Todos tienen inverso:
2 · 4 ≡ 1, 3 · 5 ≡ 1, 6 · 6 ≡ 1.

En otros sistemas se usa un módulo compuesto, pero se elige de modo que ciertos valores sean coprimos con él. El algoritmo extendido de Euclides permite comprobar y calcular esos inversos.

29.7 Criptografía simétrica y asimétrica

En criptografía simétrica, emisor y receptor comparten una misma clave secreta; es muy eficiente para cifrar grandes cantidades de datos. En criptografía asimétrica se usa un par de claves: una pública y una privada relacionada matemáticamente.

Simétrica: una clave secreta compartida.
Asimétrica: clave pública para verificar o cifrar; clave privada para firmar o descifrar.

En la práctica se combinan: la asimétrica establece o protege una clave simétrica y la simétrica protege los datos.

La aritmética modular se usa con especial notoriedad en sistemas asimétricos. Pero un protocolo seguro requiere además formatos, autenticación, aleatoriedad y protección contra ataques de implementación.

29.8 Idea general de RSA

RSA es un sistema de clave pública basado en un módulo n que es producto de dos primos grandes. Se publica n junto con un exponente e y se mantiene secreto un exponente d relacionado con e.

Clave pública: (n, e).
Clave privada: d, junto con material secreto asociado.

Cifrado didáctico: c ≡ me (mod n).
Descifrado didáctico: m ≡ cd (mod n).

La relación entre e y d se define usando propiedades de los enteros coprimos con n. Conocer la factorización de n permite construir d; sin esa información, hacerlo para parámetros grandes se considera difícil.

29.9 Construcción didáctica de un ejemplo RSA

Usaremos primos deliberadamente pequeños para observar las cuentas. Estos valores no proporcionan ninguna seguridad y nunca deben usarse fuera de un ejercicio.

p = 61, q = 53.
n = p·q = 3233.
φ(n) = (p - 1)(q - 1) = 3120.

Elegimos e = 17, coprimo con 3120.
d = 2753, porque 17·2753 ≡ 1 (mod 3120).

La clave pública del ejemplo es (3233, 17). El exponente privado es 2753. En un sistema real, los primos deben ser generados de forma segura y tener tamaños muy grandes.

29.10 Cifrado y descifrado RSA de juguete

Si el mensaje numérico es m = 65, ciframos elevando a e módulo n. Para recuperar el mensaje, elevamos el resultado a d módulo n.

c = 6517 mod 3233 = 2790.
m = 27902753 mod 3233 = 65.

El mensaje debe estar en el rango 0 ≤ m < n.

El ejemplo muestra la operación algebraica, no un formato de cifrado seguro. RSA real necesita relleno probabilístico y reglas de codificación estandarizadas para evitar ataques conocidos.

29.11 Ejecutar el ejemplo con BigInt

const n = 3233n;
const e = 17n;
const d = 2753n;
const mensaje = 65n;

const cifrado = potenciaModBigInt(mensaje, e, n);
const recuperado = potenciaModBigInt(cifrado, d, n);

console.log(cifrado);    // 2790n
console.log(recuperado); // 65n

Este código solo debe utilizarse como demostración en el navegador o en clase. No administra claves, no implementa relleno, no genera aleatoriedad segura y no protege contra ataques de canal lateral.

29.12 El inverso modular al generar d

El valor d no se adivina: se calcula como el inverso modular de e respecto de φ(n), o de una cantidad relacionada usada por la variante concreta del sistema.

e·d ≡ 1 (mod φ(n)).

17·2753 = 46801.
46801 = 15·3120 + 1.
Por eso 2753 es un inverso de 17 módulo 3120.

El algoritmo extendido de Euclides permite hallar este inverso de manera eficiente. Aquí se ve directamente cómo los temas 27 y 28 se integran en una aplicación criptográfica.

29.13 Intercambio de claves Diffie-Hellman

El intercambio de claves Diffie-Hellman permite que dos participantes acuerden un secreto compartido sobre un canal observado por terceros. Cada uno elige un exponente privado y publica una potencia modular.

Parámetros públicos: un módulo p y una base g.
Alicia publica A = ga mod p.
Bob publica B = gb mod p.

Ambos calculan el secreto: Ba ≡ Ab ≡ gab (mod p).

Quien observa p, g, A y B no debería poder recuperar el secreto con parámetros correctos. Para ser seguro, el intercambio debe autenticarse; sin autenticación es vulnerable a un atacante que se interpone entre las partes.

29.14 Ejemplo didáctico de Diffie-Hellman

Tomemos p = 23 y g = 5. Alicia elige a = 6 y Bob elige b = 15. Todos estos valores son demasiado pequeños para brindar seguridad.

A = 56 mod 23 = 8.
B = 515 mod 23 = 19.

Alicia: 196 mod 23 = 2.
Bob: 815 mod 23 = 2.

Ambos obtienen el secreto compartido 2.

El secreto de ejemplo se expone enseguida por fuerza bruta. Su valor pedagógico está en mostrar que los dos cálculos finales son congruentes, no en proporcionar un mecanismo utilizable.

29.15 Firmas digitales

Una firma digital permite verificar que un mensaje fue autorizado por quien posee una clave privada y que no se modificó desde que se firmó. Normalmente se firma un resumen criptográfico del mensaje, no el mensaje completo.

La clave privada produce la firma.
La clave pública verifica la firma.

La verificación debe fallar si cambian el mensaje, la firma o la clave pública.

Las firmas no son simplemente «cifrar con la clave privada». Los esquemas modernos especifican con precisión el resumen, el formato y los pasos de verificación para impedir falsificaciones.

29.16 Hashes, códigos de autenticación y cifrado

Estos conceptos suelen confundirse, pero cumplen funciones distintas:

Hash criptográfico: resumen de longitud fija; no se recupera el mensaje desde el hash.
MAC: verifica integridad y autenticidad con una clave compartida.
Cifrado: permite recuperar el mensaje con una clave.
Firma digital: prueba de autenticidad verificable con una clave pública.

Aplicar la herramienta equivocada deja objetivos sin cubrir. Por ejemplo, un hash público detecta cambios accidentales, pero no impide que un atacante reemplace mensaje y hash por otros coherentes.

29.17 Aleatoriedad criptográfica

Las claves privadas, los valores secretos temporales y ciertos rellenos deben ser impredecibles. Un generador habitual para simulaciones, como Math.random(), no está diseñado para esta tarea.

function bytesAleatorios(cantidad) {
  const bytes = new Uint8Array(cantidad);
  crypto.getRandomValues(bytes);
  return bytes;
}

console.log(bytesAleatorios(16));

La API Web Crypto proporciona primitivas del entorno para aplicaciones web. Aun así, usar bytes aleatorios correctamente requiere respetar el protocolo y el formato definidos por el algoritmo, no inventar una clave a partir de un ejemplo.

29.18 Errores de implementación

Un algoritmo matemáticamente correcto puede ser inseguro si se implementa mal. La criptografía práctica exige más que operar módulo un número grande.

Riesgos comunes:
usar parámetros pequeños o claves reutilizadas;
omitir relleno o autenticación;
usar aleatoriedad predecible;
filtrar información por tiempo de ejecución o mensajes de error;
guardar o transmitir claves privadas sin protección.

La regla profesional es no diseñar primitivas criptográficas propias. Se eligen algoritmos y bibliotecas mantenidos, con formatos e interfaces que reduzcan la posibilidad de uso incorrecto.

29.19 Criptografía y tamaños de enteros

La seguridad de varios sistemas depende de trabajar con enteros de cientos o miles de bits. Los ejemplos de este tema usan números pequeños porque son legibles; no representan el tamaño necesario en un sistema real.

JavaScript dispone de BigInt para enteros exactos arbitrarios, pero esa capacidad no reemplaza una biblioteca criptográfica. También importan la generación de parámetros, la resistencia a ataques de tiempo y la interoperabilidad con formatos estándar.

29.20 Aplicaciones cotidianas

Las operaciones modulares aparecen detrás de acciones habituales: establecer una conexión segura con un sitio web, verificar actualizaciones de software, almacenar contraseñas mediante funciones especializadas y autenticar mensajes entre servicios.

Navegación segura: autenticación y establecimiento de claves.
Actualizaciones: firmas digitales para verificar el origen.
Servicios: MACs o firmas para proteger mensajes.
Almacenamiento de contraseñas: funciones de derivación diseñadas para ese fin.

La aplicación correcta depende del objetivo de seguridad. Por ejemplo, las contraseñas no deben cifrarse con un ejemplo RSA ni resumirse con una función rápida sin un esquema específico de almacenamiento.

29.21 Ejercicios conceptuales

  • Explica por qué el exponente d de RSA debe ser inverso de e módulo una función del módulo n.
  • Con p = 23, g = 5, a = 6 y b = 15, comprueba las dos formas de obtener el secreto compartido.
  • Indica qué propiedad aporta una firma digital que no aporta un cifrado simétrico por sí solo.
  • Justifica por qué los números del ejemplo RSA no pueden usarse para proteger información real.

29.22 Errores frecuentes

  • Creer que ocultar el algoritmo es suficiente para proteger una clave.
  • Tomar ejemplos numéricos pequeños como configuraciones seguras.
  • Usar Math.random() para generar material criptográfico.
  • Confundir cifrado, hash, MAC y firma digital.
  • Implementar RSA sin relleno o usar una clave pública sin autenticarla.
  • Usar código didáctico de aritmética modular para proteger datos reales.

29.23 Qué debes recordar y conclusión

  • La potenciación modular eficiente es una operación básica de muchos sistemas criptográficos.
  • Los números primos, la coprimalidad y los inversos modulares permiten construir transformaciones algebraicas útiles.
  • RSA usa un par de claves y una relación modular entre sus exponentes.
  • Diffie-Hellman permite acordar un secreto, pero necesita autenticación para evitar intermediarios.
  • Hashes, MACs, cifrado y firmas digitales resuelven problemas de seguridad diferentes.
  • La matemática es necesaria, pero las implementaciones reales requieren bibliotecas, formatos y protocolos auditados.

La aritmética modular proporciona la estructura matemática de varias herramientas de seguridad, pero la criptografía práctica exige rigor en cada capa. En el próximo tema cambiaremos de perspectiva y estudiaremos el principio del palomar, una técnica de conteo para demostrar que ciertas colisiones son inevitables.