Implementación de Diffie-Hellman en Línea de Comandos

Clase 17 de 25Curso de Fundamentos de Criptografía

Contenido del curso

Criptografía Asimétrica

Resumen

Llevar la teoría del algoritmo de Diffie-Hellman a código funcional es uno de los pasos más valiosos para comprender la criptografía en la práctica. A continuación se recorre paso a paso cómo construir una herramienta de línea de comandos en Node.js que permite a dos partes —Alice y Bob— acordar un secreto compartido sin exponerlo públicamente.

¿Cómo se estructura el comando de Diffie-Hellman en la CLI?

El punto de partida es añadir un nuevo comando a la interfaz de línea de comandos que ya se venía construyendo. A diferencia de comandos anteriores, este requiere múltiples argumentos: número primo, generador, llave pública, llave privada y encoding. Cada argumento acepta un encoding cuyo valor por defecto es hexadecimal, tal como se manejó en ejercicios previos [0:24].

Después se crea una carpeta dedicada al algoritmo con su archivo index.ts, donde se importa la librería crypto de Node:

ts import crypto from 'crypto';

La función exportada por defecto manejará dos flujos: uno cuando no existe contraparte (se es la primera parte que genera llaves) y otro cuando se reciben los parámetros de la contraparte para computar el secreto.

¿Qué sucede cuando no hay contraparte y se generan las llaves?

Cuando Alice inicia el intercambio, no dispone de información de Bob. En ese caso se utiliza crypto.createDiffieHellmanGroup con un grupo predefinido —en este ejemplo modp14— que proporciona un número primo grande listo para usar [2:42].

¿Por qué usar grupos predefinidos como modp14?

El algoritmo de Diffie-Hellman depende de un número primo grande como base de seguridad. Dado que elegir un primo adecuado manualmente es complejo, la librería trae grupos precargados. El grupo modp14 ofrece seguridad equivalente a 128 bits [2:55].

Con el grupo instanciado, se obtienen automáticamente el primo y el generador:

ts const dh = crypto.createDiffieHellmanGroup('modp14'); const publicKey = dh.generateKeys().toString(encoding); const prime = dh.getPrime().toString(encoding); const generator = dh.getGenerator().toString(encoding); const privateKey = dh.getPrivateKey().toString(encoding);

Esta información se retorna para que Alice pueda compartir su llave pública, el primo y el generador con Bob, sin compartir jamás la llave privada [3:50].

¿Cómo computa Bob el secreto compartido?

Cuando existe contraparte, Bob recibe de Alice el número primo, el generador y la llave pública. Además, genera su propia llave privada. Con estos datos se instancia Diffie-Hellman pasando primo y generador con sus respectivos encodings [5:07]:

ts const dh = crypto.createDiffieHellman(prime, primeEncoding, generator, generatorEncoding); dh.setPrivateKey(privateKey, privateKeyEncoding); const secret = dh.computeSecret(publicKey, publicKeyEncoding);

El método computeSecret toma la llave pública de la contraparte y, combinándola con la llave privada propia, produce el secreto compartido. Este valor se retorna junto con el resto de parámetros.

¿Cómo se verifica que ambas partes obtienen el mismo secreto?

Para simular el intercambio se abren dos terminales: una representando a Alice y otra a Bob [7:15]. Al ejecutar el comando sin contraparte en ambas ventanas, se observa que:

  • Las llaves públicas generadas son distintas.
  • Las llaves privadas son distintas.
  • El primo y el generador coinciden, pues usan el mismo grupo.

A continuación se ejecuta el comando con los parámetros cruzados —cada parte pasa su propia llave privada y la llave pública de la otra— junto con el primo y el generador compartidos [8:05]. El resultado confirma que el secreto computado es idéntico en ambos lados, aunque las llaves privadas y públicas difieran.

Esto demuestra el principio fundamental del key exchange: dos partes acuerdan una llave simétrica sin que esta viaje por el canal de comunicación. Nadie que intercepte la llave pública, el primo o el generador puede reconstruir el secreto sin la llave privada correspondiente.

Ahora que tienes tu propia implementación funcional, comparte tu llave pública, primo y generador en los comentarios para practicar el intercambio con otros estudiantes y enviar mensajes cifrados.