domingo, 26 de febrero de 2017

Criptografía (XLIX): el algoritmo DES (I)

DES (Data Encryption Standard) fue desarrollado por IBM a petición de la Oficina Nacional de Estandarización (National Bureau of Standards) de los Estados Unidos. Su diseño se basó en otro algoritmo anterior, Lucifer, y fue adoptado como estándar de cifrado en 1976 por el Gobierno de los EE.UU.

Es un algoritmo de cifrado simétrico (se utiliza la misma clave para cifrar y para descifrar) por bloques (la información a cifrar se divide en bloques y se aplica el algoritmo a cada uno de ellos) que se basa en una estructura denominada Red de Feistel (cifrado de producto iterativo de n rondas en el que la salida de cada una de ellas se usa como entrada en la siguiente).

Este algoritmo opera sobre bloques de 64 bits del texto en claro, dividiendo cada uno de ellos en dos mitades, L (los 32 bits de la izquierda) y R (los 32 bits de la derecha), y emplea una clave de 56 bits.

Básicamente, el cifrado consiste en una permutación inicial, una Red de Feistel de 16 rondas (16 iteraciones en las que se repiten una serie de operaciones: permutaciones, aritmética modular y sustituciones. Ver conceptos de difusión, confusión y cifrado de producto en este post) y una permutación final.

En principio la longitud de la clave (K) es de 64 bits, pero el bit menos significativo de cada byte se ignora, por lo que sólo se emplean 56 bits.

Si no lo he entendido mal, su funcionamiento sería el siguiente:

1.- Como paso previo al cifrado, a partir de la clave de 64 bits se calculan 16 subclaves (Ki) de 48 bits cada una (una para cada ronda).

1.1.- Permutación de los bits de K conforme a la posición de cada uno de ellos que se indica en la siguiente tabla:
Nótese que en esta tabla no figuran los bits menos significativos de cada byte (8, 16, 24, 32, 40, 48, 56 y 64), por lo que éstos son ignorados (como he dicho antes, en la práctica se emplean 56 bits de la clave).

Pongo un ejemplo:
1.2.- Ahora, los bits de la mitad izquierda (C0) y de la mitad derecha (D0), obtenidas tras la permutación PC-1, ambas de 28 bits, se van rotando circularmente a la izquierda conforme al número de bits a desplazar a la izquierda que se indica en la siguiente tabla:
Es decir, el número de bits a desplazar a la izquierda es 2, excepto para las iteraciones 1, 2, 9 y 16 en las que se desplaza sólo 1 bit a la izquierda.

En nuestro ejemplo:
1.3.- Tras cada una de las iteraciones anteriores se aplica la permutación PC-2 a  los bits de la concatenación de Ci || Di (donde £ i £ 16), conforme a la posición de cada uno de ellos que se indica en la siguiente tabla:
Y, de esta forma, se obtienen las 16 subclaves (Ki; donde £ i £ 16); como he dicho antes, cada una de ellas con una longitud de 48 bits. Siguiendo con nuestro ejemplo:
Hasta el momento, gráficamente:
Y ahora ya se está en disposición de cifrar el texto en claro.

2.- Cifrado: Supongamos que vamos a cifrar un bloque (64 bits) del texto en claro. El siguiente:

M = 0100 0101 0100 1010 0100 0101 0100 1101 0101 0000 0100 1100 0100 1111 0100 1101


2.1.- Se aplica una permutación inicial (IP) a los bits del bloque a cifrar conforme a la posición de cada uno de ellos que se indica en la siguiente tabla:
En nuestro ejemplo:
2.2.- A partir de aquí el algoritmo realiza 16 rondas utilizando una función (f), de la siguiente manera:
Es decir, en cada ronda, la mitad derecha pasa a ser la mitad izquierda de la siguiente iteración y la mitad izquierda, a la que se suma módulo 2 (operador lógico XOR u o-exclusivo) el resultado de la función f, pasa a ser la mitad derecha.

Gráficamente:
La función f consta de: una permutación de expansión (E) - que transforma el bloque de 32 bits de la entrada en uno de 48 bits, permutando los bits que recibe y duplicando algunos de ellos -, una operación XOR con el valor de la subclave correspondiente (Ki), 8 operaciones de sustitución aplicadas a cada uno de los 8 bloques de 6 bits en los que se divide el resultado de la operación XOR anterior y otra permutación (P).

Gráficamente:
2.2.1.- La permutación de expansión (E) se realiza conforme a la posición de cada uno de los bits de entrada que se indica en la siguiente tabla:
Nótese que algunos de los bits que recibe (32 bits) se duplican para obtener una salida de 48 bits, con objeto de poder realizar la operación XOR con la subclave (Ki) correspondiente, que tiene una longitud de 48 bits.

En nuestro ejemplo, para la primera iteración (entrada R0):
2.2.2.- Operación XOR con el valor de la subclave correspondiente:
En nuestro ejemplo y para la primera ronda:
2.2.3.- Las sustituciones se realizan mediante unas tablas denominadas S-Cajas (en inglés S-Boxes, Substitution Boxes).

Para ello, en primer lugar se divide el resultado anterior en 8 bloques de 6 bits cada uno, de la siguiente manera:
Y, posteriormente, cada uno de estos bloques es la entrada a su respectiva S-Caja, cada una de las cuales determina la sustitución a realizar de la siguiente manera:

El primer y último bit de cada bloque (Bi) indican la fila de la S-Caja (Si) a seleccionar y los cuatro bits centrales determinan la columna, devolviéndose el valor (4 bits) que se encuentra en la intersección de ambas.

En nuestro ejemplo, para la primera ronda y primera S-Caja (S1):
Las tablas de las S-Cajas son las siguientes:
2.2.4.- Por último, el resultado de la función f de cada ronda se obtiene aplicando una permutación (P) a la concatenación (32 bits) de los resultados obtenidos tras realizar cada una de las sustituciones anteriores, que devuelve un bloque también de 32 bits.
Y se repite el paso 2.2. hasta completar las 16 rondas.

2.3.- Finalmente, se aplica una permutación inversa a la permutación inicial (IP-1), conforme a la posición de cada uno de los bits de la concatenación de R16 y L16 obtenidos en la última ronda:
El resultado de aplicar esta permutación final es el criptograma (C).

Para ver si lo he entendido correctamente (con tanta confusión y difusión reconozco estar yo mismo un tanto confuso y difuso :)), en el próximo post pondré el resultado completo del cifrado del ejemplo y en otro posterior su descifrado, aunque ya adelanto que para el descifrado bastará con aplicar las subclaves (Ki) en orden inverso.

martes, 21 de febrero de 2017

Criptografía (XLVIII): cifrado autoclave

En este post, antes de continuar con las entradas relativas a la criptología moderna, vuelvo a referirme a un criptosistema clásico, el cifrado autoclave.

Se trata de una variante del cifrado de Vigenère en la que se utiliza una clave primaria que se emplea para cifrar/descifrar los primeros caracteres y el cifrado/descifrado del resto se realiza utilizando como siguientes caracteres de la clave los del propio texto en claro, es decir, realmente la clave consiste en la concatenación de la clave primaria más el texto en claro.

De esta forma se consigue que la clave sea más larga que el propio mensaje a cifrar y, entre otras cosas, que no sea posible el criptoanálisis mediante el método Kasiski, ya que no se emplea una clave periódica.

Veamos un ejemplo:

1.- Texto en claro a cifrar (M): EJEMPLOCIFRADOAUTOCLAVE.

2.- Clave primaria (Kp): CLAVE.

3.- Clave (K)Kp & M.

Es decir:
4.- Cifrado: de la misma forma que en el cifrado de Vigenère, es decir, utilizando la tabla con los caracteres de español ("Ñ" incluido) o, lo que es lo mismo, la función de cifrado indicada en este post.
Ek(m1) = (m1 + k1) mod 27 = (E + C) mod 27 = (4 + 2) mod 27 = 6 = G = c1
Ek(m2) = (m2 + k2) mod 27 = (J + L) mod 27 = (9 + 11) mod 27 = 20 = T = c2
Ek(m3) = (m3 + k3) mod 27 = (E + A) mod 27 = (4 + 0) mod 27 = 4 = E = c3
Ek(m4) = (m4 + k4) mod 27 = (M + V) mod 27 = (12 + 22) mod 27 = 7 = H = c4
Ek(m5) = (m5 + k5) mod 27 = (P + E) mod 27 = (16 + 4) mod 27 = 20 = T = c5
Ek(m6) = (m6 + k6) mod 27 = (L + E) mod 27 = (11 + 4) mod 27 = 15 = O = c6
...
Ek(m11) = (m11 + k11) mod 27 = (R + L) mod 27 = (18 + 11) mod 27 = 2 = C = c11
...

Y así sucesivamente hasta obtener el texto cifrado o criptograma: GTEHTO...

5.- Descifrado:

5.1.- En primer lugar se descifran los caracteres del criptograma correspondientes a los caracteres de la clave primaria (Kp), que en nuestro caso es "CLAVE":
DKp(c1) = (c1 - kP1) mod 27 = (G - C) mod 27 = (6 - 2) mod 27 = 4 = E = m1
DKp(c2) = (c2 - kP2) mod 27 = (T - L) mod 27 = (20 - 11) mod 27 = 9 = J = m2
DKp(c3) = (c3 - kP3) mod 27 = (E - A) mod 27 = (4 - 0) mod 27 = 4 = E = m3
DKp(c4) = (c4 - kP4) mod 27 = (H - V) mod 27 = (7 - 22) mod 27 = 12 = M = m4
DKp(c5) = (c5 - kP5) mod 27 = (T - E) mod 27 = (20 - 4) mod 27 = 16 = P = m5

5.2.- Después se continúa descifrando el criptograma utilizando los caracteres descifrados hasta el momento (en nuestro caso los cinco primeros caracteres del texto en claro) como los siguientes caracteres de la clave:

DK(c6) = (c6 - m1) mod 27 = (O - E) mod 27 = (15 - 4) mod 27 = 11 = L = m6
...

Y así sucesivamente:

DK(c11) = (c11 - m6) mod 27 = (C - L) mod 27 = (2 - 11) mod 27 = 18 = R = m11
...

hasta obtener el texto en claro completo: EJEMPL...

martes, 14 de febrero de 2017

Criptografía (XLVII): Descifrado RSA, ¿un "trabajo de chinos"?

Uno de los estereotipos con relación a los chinos es que éstos son muy laboriosos, pacientes y meticulosos en el trabajo, por lo que entiendo que el dicho popular "trabajo de chinos" hace referencia a aquel que es largo, tedioso y/o complicado.

Pero, ¿qué tiene que ver ésto con el descifrado utilizando el algoritmo RSA?.

Me explico: tal y como sabemos, en criptografía híbrida, el algoritmo RSA se emplea para cifrar la clave de sesión (un número aleatorio correspondiente a cada mensaje particular) con la clave pública del receptor y que después este último descifra utilizando su clave privada (criptografía asimétrica) para, a su vez, poder después descifrar el criptograma empleando la clave de sesión (criptografía simétrica).

Supongamos que para cifrar el texto en claro se utiliza el algoritmo de criptografía simétrica AES (longitud de la clave de 256 bits). Por tanto, para cifrar la clave de sesión (k) mediante RSA se realizará la siguiente operación: c = ke mod n, donde k tiene un tamaño de 256 bits, para e se recomienda utilizar valores relativamente pequeños para forzar que d tenga un tamaño en bits del orden del módulo, y n de 2048 bits.

Por consiguiente, para el descifrado de la clave de sesión se realizará la siguiente operación: k = cd mod n, donde c puede tener un tamaño de 2048 bits, d será del orden de 2048 bits y n de 2048 bits, lo que efectivamente tiene pinta de ser, por costoso, un auténtico "trabajo de chinos".

Bueno, pues que lo resuelvan los chinos..., y efectivamente también así es, ya que para simplificar los cálculos en el descifrado se suele utilizar el teorema chino del resto.

Utilizando este teorema y mediante los números primos p y q cuyo producto es el módulo (n), los cálculos a realizar en el descifrado, tal y como veremos más adelante, serán sensiblemente más rápidos. Nótese que los números p y q son secretos y, por tanto, que ésto sólo puede realizarlo el receptor del mensaje.

Para ello, junto con su clave privada (d, n), el receptor debe guardar los números primos p y q, y, además, para aplicar de forma óptima este teorema en el descifrado, los siguientes valores:

1.- p1 = p-1 mod q

2.- dp = d mod (p – 1)

3.- dq = d mod (q  1)

De esta forma sólo debemos calcular estos valores un sola vez y evitamos tener que hacerlo en cada descifrado.

Ahora, por lo que he entendido, el descifrado se realizaría de la siguiente manera:

1.- Calculamos:

1.1.- cp = c mod pcq = c mod q

1.2.- k1 = cpdp mod pk2 = cqdq mod q

2.- Resultado: k = k1 + p (((k2  k1) p1) mod q)

Veamos un ejemplo, pero esta vez con números un poco más grandes de aquellos que vengo utilizando en esta serie de posts, aunque todavía mucho más pequeños de los que se emplean actualmente en RSA. De esta forma veremos mejor la ventaja que supone aplicar este teorema en el descifrado.

Previamente al ejemplo, genero un par de claves y realizo la operación de cifrado de una clave de sesión (k):

1.- p = 26.317; q = 30.269; n = p q26.317 x 30.269 = 796.589.273j(n) = (p  1)(q  1) = 26.316 x 30.268 = 796.532.688; e = 65.537; mcd(e, j(n)) = mcd(65.537, 796.532.688) = 1; d = inv(e, j(n)) = inv(65.537, 796.532.688) = 329.140.817 

2.- Clave pública del receptor (e, n): (65.537, 796.589.273)

3.- Clave privada del receptor (d, n): (329.140.817, 796.589.273)

4.- Clave de sesión (k) a cifrar mediante RSA: 505.316.708

5.- Cifrado: c = ke mod n = 505.316.70865.537 mod 796.589.273 = 670.835.545

Y ahora el ejemplo: el receptor tiene guardados, junto a su clave privada (329.140.817, 796.589.273), p = 26.317, q = 30.269 y  los siguientes valores previamente calculados: p1 = p-1 mod q = 17.685; dp = d mod (p – 1) = 329.140.817 mod 26.316 = 6.605; dq = d mod (q  1) = 329.140.817 mod 30.268 = 6.585, con lo que, si lo he entendido bien, el descifrado sería como sigue:

1.- cp = c mod p = 670.835.545 mod 26.317 = 15.215; cq = c mod q =  670.835.545 mod 30.269 = 13.967

2.- k1 = cpdp mod p = 15.2156.605 mod 26.317 = 3.991; k2 = cqdq mod q =  13.9676.585 mod 30.269 = 6.022

3.- k = k1 + p (((k2  k1) p1) mod q) = 3.991 + 26.317 (((6.022  3.991) 17.685) mod 30.269) = 3.991 + 26.317 x 19.201 = 505.316.708

Y, por tanto, parece que "los chinos han hecho bien su trabajo" :), ya que como se puede observar el resultado del descifrado coincide con la clave de sesión (k) que se ha cifrado.

Nótese que el paso más costoso del descifrado es el paso 2, en el que se realizan dos operaciones de exponenciación modular con bases con una longitud de 14 bits, exponentes de 13 bits y módulos de 15 bits, mientras que si no utilizáramos este teorema el descifrado se realizaría mediante la siguiente operación: k = cd mod n = 670.835.545329.140.817 mod 796.589.273 = 505.316.708, es decir, una operación de exponenciación modular con una base de longitud 30 bits, un exponente de 29 bits y un módulo de 30 bits.

Con lo que tal y como se observa, la ventaja fundamental de aplicar este teorema consiste en que mientras la clave privada (d) tiene una longitud del orden del tamaño del módulo (en nuestro caso 29 y 30 bits, respectivamente), dp y dq tienen una longitud aproximadamente de la mitad (en nuestro caso 13 bits) y, además, estos dos últimos valores pueden calcularse previamente una sola vez y guardarse para ser utilizados en descifrados posteriores.   

sábado, 11 de febrero de 2017

Criptografía (XLVI): RSA y los números primos grandes, ¿"la pescadilla que se muerde la cola"?

Tal y como he venido comentado en la serie de posts dedicados al algoritmo RSA, quizá el criptosistema de clave pública más utilizado en la actualidad, éste se basa en la elección de dos números primos aleatorios lo suficientemente grandes (actualmente del orden de 200 dígitos decimales cada uno de ellos) para generar el par de claves (pública y privada) correspondiente a cada usuario.

También decía en un post anterior que no es trivial conocer si un número lo suficientemente grande es primo o compuesto y que, para ello, podíamos caer en la "tentación" de intentar factorizarlo. Craso error, pues tal y como también he venido insistiendo en esta serie de posts, nos enfrentaríamos precisamente con aquello en lo que se basa la fortaleza de este cifrado: actualmente ésto no es posible en un tiempo mínimamente razonable.

Entonces: ¿Cómo seleccionamos aleatoriamente los dos números primos grandes para generar el par de claves correspondiente a un usuario?, es decir, ¿Cómo "determinamos" que los números primos aleatorios elegidos son primos sin intentar factorizarlos?, ¿Es la "pescadilla que se muerde la cola"?.

Pues no, tal y como también decía en este post, afortunadamente existen algoritmos probabilísticos que nos pueden decir con un alto nivel de confianza si un número dado es primo, aunque no haya certeza matemática (100%) al respecto.

Veamos uno de los tests de primalidad más utilizados, el de Miller-Rabiny algunos ejemplos.

Si no lo he entendido mal, el algoritmo para aplicar este test a un número dado para conocer si éste es primo (con un alto nivel de confianza) o compuesto podría ser el siguiente:
Veamos algunos ejemplos:

1.- Partiendo del ejemplo que vengo utilizando en esta serie de posts: ¿es el 997 un número primo?:

Aunque con un número tan pequeño es trivial conocer si es primo o no (ya sabemos que sí lo es) veamos que ocurre aplicando el test de primalidad de Miller-Rabin:
2.- Pero quizá no sea tan trivial saber si el 286.467.789.841 es un número primo. Veamos que ocurre en esta ocasión.
Y como para demostrar que un número es compuesto no hay mejor demostración que enseñar los factores no triviales cuyo producto da ese número: 298.817 x 958.673 = 286.467.789.841.

3.- Y, finalmente: ¿es el 275.415.303.169 un número primo?:
En este caso, el test nos dice que probablemente (con un muy elevado nivel de confianza) este número es primo, aunque como digo no se trata de un test determinista y por tanto creérselo es una cuestión de fe :), aunque yo sé que efectivamente sí lo es.

lunes, 6 de febrero de 2017

Criptografía (XLV): ¿Sabías que...? (IX)

Quizá la aplicación práctica más "palpable" de los números primos se dé actualmente en la criptografía, ya que en ellos descansa en gran medida el secreto de nuestras más preciadas comunicaciones en Internet.

Así, los números primos son la base del algoritmo RSA, posiblemente el criptosistema de clave pública más utilizado en la actualidad, en el cuál el par de claves (pública y privada) correspondiente a cada usuario se calcula a partir de dos números primos aleatorios lo suficientemente grandes.

La fortaleza de este algoritmo reside en el elevado coste computacional de hallar los dos factores primos de un número lo suficientemente grande resultado del producto de ambos, aunque este último sea público y, por tanto, pueda ser conocido por cualquiera, ya que esta tarea no es factible en un tiempo razonable con los algoritmos de factorización conocidos que se pueden implementar hasta la fecha y con la potencia de cálculo de los ordenadores actuales, por mucha de esta última de la que se disponga. Por tanto, esos números primos son fundamentales para salvaguardar la confidencialidad de nuestras comunicaciones en Internet y deben mantenerse en secreto, ya que su conocimiento por parte de terceras personas haría inútil cualquier esfuerzo al respecto.

Sin embargo, pese a esa "palpable" aplicación práctica en la criptografía que comentaba al principio, ni siquiera somos conscientes de que utilizamos todo esto en nuestra vida cotidiana en nuestras relaciones por Internet con las administraciones públicas, entidades bancarias, etc.

Ya he escrito en este blog diferentes entradas sobre el algoritmo RSA (ver primer post) y aquí me centraré en los aspectos básicos de los números primos que a mí me parecen más curiosos y de éstos aplicados a la criptografía.

Dicho ésto, a todos nos enseñaron en el colegio que los números primos son aquellos números naturales mayores que 1 que únicamente son divisibles por sí mismos y por la unidad, y que los números compuestos, en contraposición a éstos, son aquellos números naturales que tienen otro u otros divisores diferentes además de sí mismos y de 1, pero, al menos que yo recuerde, sin darnos mayores explicaciones ni de su historia, ni de para qué sirven.

1.- ¿Es el 1 un número primo o compuesto?:

Pues parece ser que ni una cosa ni otra, pero sólo por convención y de forma relativamente reciente, es decir y en mi opinión, porque "estorba que sea una cosa u otra" :), ya que si fuera primo o compuesto habría que volver a formular importantes teoremas dando explicaciones adicionales.

2.- ¿Desde cuando se conoce la existencia de los números primos?:

No se sabe con certeza, ya que hay quien afirma que este conocimiento podría remontarse bastantes miles de años atrás, pero sí se puede datar con seguridad, como mínimo, alrededor del año 300 a.C.

Así, Euclides define en esa época los números primos y, poco más tarde, Eratóstenes idea un método para hallar todos los números primos menores o iguales que un número dado.

Por tanto, al menos, hace ya más de 2.000 años que los matemáticos vienen estudiando los números primos. Quizá les fascinaron porque, tal y como se dice, son los "átomos" de los que están constituidos todos los números naturales, es decir, cualquier número natural se puede descomponer en un producto de factores primos.

La criba de Eratóstenes para hallar todos los números primos menores o iguales que uno dado consistía en lo siguiente:

1.- Se escriben en forma de tabla todos los números naturales hasta aquel del que queremos hallar todos los números primos menores o iguales que él, incluido este último.

2.- Se tacha el 1, porque como ya he dicho no es un número primo.

3.- Se va hasta el siguiente número no tachado y, si el cuadrado de éste no es mayor que el número del que queremos hallar todos los números primos menores o iguales que él, este número es declarado como primo y se tachan todos los números de la tabla que sean múltiplo de él, y se vuelve a repetir este paso 3.

4.- Cuando el cuadrado del siguiente número no tachado sea mayor que el número del que queremos hallar todos los números primos menores o iguales que él, se declaran como primos todos los números no tachados de la tabla.

Ejemplo: supongamos que queremos obtener todos los números primos menores o iguales a 100.

Gráficamente:

Creo que el algoritmo podría ser, más o menos, el siguiente:
En nuestro caso:
3.- ¿Cuántos números primos hay?:

Euclides fue el primero en formular una demostración sobre la infinitud de los números primos: "El conjunto formado por los números primos es infinito".

4.- ¿Es "fácil" determinar si un número dado es primo o compuesto?:

A la condición de que un número sea primo se le denomina primalidad y, por tanto, a la cuestión de determinar si un número dado es primo o compuesto se le conoce como el problema de la primalidad.

Así, a primera vista, éste parece un problema "fácil" (más que a "fácil" la pregunta debería hacer referencia a poco costoso) y basándonos en la criba de Eratóstenes podríamos probar a dividir el número impar en cuestión (evidentemente éste debe ser impar, ya que el único número primo par es el 2) entre todos los números enteros impares positivos comprendidos entre el 3 y el entero más próximo por defecto a la raíz cuadrada del número dado, pero esto es claramente inaceptable cuando el número en cuestión es lo suficientemente grande.

Una vez que desechamos este método, la siguiente "tentación" que podemos tener para dar respuesta a esta pregunta es pensar en factorizar dicho número con métodos más modernos, pero, tal y como he comentado al principio de este post, ésto, de momento, tampoco es posible en un tiempo razonable para números lo suficientemente grandes, como es el caso de RSA.

¿Es ésto importante?. Pues sí, ya que conviene recodar que RSA, el criptosistema de clave pública más utilizado en la actualidad, se basa precisamente en seleccionar aleatoriamente dos números primos grandes (cada uno de ellos del orden de 200 dígitos decimales) para generar el par de claves para cada usuario (pública y privada).

Entonces: ¿cómo se hace en la práctica para seleccionar dos números primos grandes?. Afortunadamente, existen algoritmos probabilísticos, mucho más eficientes que los de factorización, que nos pueden decir con un alto grado de confianza si un número dado es primo o compuesto, ésto es lo que se conoce como tests de primalidad, es decir, se trata de algoritmos no deterministas (no hay certeza matemática del resultado obtenido) que intentan verificar la hipótesis de que un determinado número es compuesto y si no lo consiguen aceptan que es primo con un cierto nivel de confianza.

En un post posterior, para no hacer éste excesivamente largo, compartiré lo que que voy aprendiendo sobre los tests de primalidad y pondré algunos ejemplos.  

5.- ¿Existen diferentes tipos de números primos?:

Hay multitud de clases o tipos de números primos, es decir, de subconjuntos del conjunto de números primos formados por aquellos que comparten unas determinadas características y que reciben un nombre colectivo para identificarlos. Así, entre muchas otras clases, nos encontramos, por ejemplo, con los números primos: pitagóricos, de Wieferich, etc., pero quizá los tipos de números primos con mayor aplicación en la criptografía son los primos fuertes y los primos seguros.

También, como en el caso anterior, en un post posterior compartiré lo que voy aprendiendo sobre los tipos de números primos con aplicación en la criptografía,