Interesado en conocer como funcionaban a bajo nivel los sistemas de cifrado con juegos de clave pública/privada, y al no encontrar un lugar donde se explique de manera terrenal (y no como para doctores en matemáticas) voy a tratar de escribir este artículo lo mas humanamente posible, empezando desde cero y detallando cada uno de los pasos.

La wiki dice que lo primero que tenemos hacer es buscar (de manera aleatoria) dos números primos distintos, llamados a partir de acá p y q, y multiplicarlos entre sí para obtener un nuevo número que llamaremos n.

Para continuar a partir de acá debemos refrescar unos conceptos de aritmética modular, y la mejor forma que encontré fueron unos ejemplos que detallo a continuación:

Supongamos que tenemos que sumar o restar algunas horas apoyándonos en un reloj de agujas, por ejemplo 6 horas mas después de las 8. El reloj claramente marcaría las 2 ya que al pasarnos de las 12, empezamos a contar de nuevo. Bueno, esto, en principio, sería  aritmética modular en base 12. Y podríamos definir el caso anterior como 8 + 6 mod 12 = 2.

La única diferencia con la aritmética modular es que se incluye al cero en nuestro universo de números, es por eso que si trabajamos con base 7, los números representados son {0, 1, 2, 3, 4, 5, 6}.

Con un ejemplo un poco mas complicado, si multiplicamos 3 * 5, con base 7 el resultado sería 1 (dos vueltas de reloj mas una hora), o sea 3 * 5 mod 7 = 1.

A estas operaciones también las podemos relacionar con el resto de una división, pudiendo representar esto de la siguiente manera:  15 / 7 = 2 resto 1.

Algo para resaltar es que, al igual que con los números reales, si dos números se multiplican entre sí y como resultado dan 1, es que son inversos. Así como 5 y 1/5 son inversos porque 5 * (1/5) = 1 , 3 y 5 son inversos en módulo 7 ya que 3 * 5 mod 7 = 1.

Debemos mencionar una propiedad que dice que un número x tiene inversa módulo y  si no existe ningún número mayor a 1 y menor que x e y  que los divida en forma exacta. Y a estos números se los llama primos relativos ya que no existe un divisor común mayor a 1. Por ejemplo 8  y 5 son primos relativos (aunque 8 no sea primo) ya su máximo común divisor es 1.

Seguimos un poco mas. Se conoce al número phi como a la cantidad de  números que tienen inversa para un módulo. Si continuamos con el ejemplo de modulo 7, tenemos que existen 6 números que tienen inversa (del 1 al 6) y de forma genérica se puede decir que si n es número primo, phi(n) es igual a n – 1.

Entonces, si decimos que n está formado por dos números primos, phi(n) es igual a (p – 1) * (q – 1)

Vamos a completar este caso con un ejemplo:

p = 3

q = 11

n = p * q = 3 * 11 = 33

phi(n) = 2 * 10 = 20

Generación de las claves

La clave pública será un número aleatorio que sea primo relativo entre 1 y phi(n) al cual llamaremos e, y para nuestro caso podemos usar el 7.

A la inversa la llamaremos d y surge, como ya dijimos, de obtener el número que multiplicado por e nos de 1 mod(phi(n)). Mucho me costo entender esta última parte y me quedo mas que claro después de leer varios ejemplos, así que vamos con uno:

Dijimos que:

e = 7 (exponente público)

entonces, para encontrar d tenemos que iterar desde 1 hasta 20  (o sea phi(n)) tratando de ubicar un número tal que multiplicado por 7 nos de 1 en módulo 20 (o sea phi(n)).

7 * d = 1 mod (20)

7 * 3 = 21

21 mod 20 = 1

d = 3 (exponente privado)

Ahora si tenemos todo como para armar la clave pública y la clave privada, y ambas se definen de la siguiente manera:

Clave Pública: (n, e) o (33, 7)

Clave Privada: (n,d) o (33, 3)

Cifrar y descifrar:

Para cifrar un mensaje, lo único que debemos hacer es elevar el dato a e (que dijimos, es el número de  la clave pública). El procedimiento para descifrar un mensaje  se apoya en una nueva propiedad que dice que si multiplicamos un número x  por sí mismo phi(n) veces, el resultado es 1 en módulo n, y en esta propiedad es donde se apoya el algoritmo RSA.

Con los datos que venimos manejando, supongamos que queremos cifrar el número 2.

dato = 2

Cifrar:

dato^e mod (n)

2 ^ 7 mod(33) = 128 mod (33) = 29 = datoCifrado

Descifrar:

datoCifrado^d mod(n)

29^3 mod(33) = 24389 mod(33) =  2 = dato