Claves de juguete: esta demo implementa el McEliece de 1978 con claves pequeñas y un generador pseudoaleatorio con semilla (para poder repetirlas y compartirlas). No la uses para proteger nada. Todo se calcula en tu navegador.

Parámetros y semilla

GF(16) entero como soporte; k = 8: se cifra un byte por bloque.

Cuánto detalle quieres ver

1 Genera las claves

La clave privada es un código de Goppa: un código corrector de errores que sabes decodificar deprisa. La pública es ese mismo código disfrazado para que parezca uno cualquiera, que es difícil de decodificar. Cada paso se despliega.

1.1 El cuerpo \mathrm{GF}(2^{4}) y su polinomio primitivo

Los números con los que trabajamos son los de \mathrm{GF}(2^{4}): polinomios en x con coeficientes 0 o 1, módulo el polinomio primitivo f(x) = x^{4} + x + 1. Tiene 2^{4} = 16 elementos: el 0 y las potencias \alpha^0, \dots, \alpha^{14}, donde \alpha es una raíz de f.

0 = 0000 α⁰ = 0001α = 0010α^2 = 0100α^3 = 1000α^4 = 0011α^5 = 0110α^6 = 1100α^7 = 1011α^8 = 0101α^9 = 1010α^10 = 0111α^11 = 1110α^12 = 1111α^13 = 1101α^14 = 1001

Cada elemento se escribe con 4 bits (los coeficientes de 1, x, x², …). Eso permite convertir una matriz sobre el cuerpo en una matriz binaria.

1.2 El polinomio de Goppa g(z), irreducible de grado t = 2

g(z) = z^{2} + \alpha^{9}\,z + 1. Se prueban polinomios mónicos de grado 2 al azar hasta encontrar uno irreducible (sin factores): han hecho falta 6 intentos. Irreducible garantiza que el código corrige 2 errores y que el algoritmo de Patterson funciona.

1.3 El soporte L: 16 elementos del cuerpo

L = (\alpha_0, \dots, \alpha_{15}): elementos distintos del cuerpo que no son raíces de g. Cada uno es el «nombre» de una posición del mensaje.

0 01 12 α3 α^24 α^35 α^46 α^57 α^68 α^79 α^810 α^911 α^1012 α^1113 α^1214 α^1315 α^14
1.4 La matriz de control H y su versión binaria

H = \left( \alpha_j^{\,i} / g(\alpha_j) \right)_{0 \le i < t,\quad 0 \le j < n}, de 2 filas y 16 columnas, sobre \mathrm{GF}(2^{4}). Un vector binario c está en el código si y solo si H c^{T} = 0. Cada elemento se desdobla en sus 4 bits y sale una matriz binaria H_{\text{bin}} de 8 × 16 (rango 8).

1α^6α^14α^9α^14αα^3α^3α^6α^51α^13α^9α^5α^13α
0α^61α^11α^2α^5α^8α^9α^13α^13α^9α^8α^5α^2α^111
1.5 La matriz generadora G (8 × 16)

Sus 8 filas son una base del código: k = n - \operatorname{rango}(H_{\text{bin}}) = 16 - 8 = 8 . Las columnas en verde forman un conjunto de información: ahí G es la identidad, así que el mensaje se lee directamente. Comprobación: H_{\text{bin}}\, G^{T} = 0 ✓.

1.6 El disfraz: S (invertible, 8 × 8) y P (permutación, 16 × 16)

S mezcla las filas de G (cambia de base el mismo código) y P reordena las columnas. S se elige al azar entre las matrices binarias hasta que sea invertible: 1 intento.

S

P (un 1 por fila y por columna): la fila i tiene su 1 en la columna π(i), con π = (15, 8, 14, 0, 10, 3, 12, 9, 4, 6, 1, 5, 11, 7, 2, 13)

1.7 La clave pública G′ = S · G · P

G' = S\,G\,P: sigue generando un código equivalente al de Goppa, pero ya no se ve su estructura; parece una matriz aleatoria. Es la clave pública, junto con t = 2. Ocupa 8 × 16 = 128 bits (16 bytes). La privada es (g, L, S, P).

2 Cifra un mensaje

Qué cifrar

El texto pasa a bytes (UTF-8) y se corta en bloques de 8 bits: un byte (una letra) por bloque. Cada bloque m se cifra por separado.

Bloquem (8 bits)e (peso 2)c = mG′ + e (16 bits)
010010002, 121011100100001100
011011118, 101100101010101010
011011008, 151001111111110101
011000017, 140000000011110011

Pulsa un bloque de la tabla para ver su detalle (aquí, el bloque 1 de 4) en los pasos de cifrado, descifrado y ataque.

Detalle del bloque 1

  1. El mensaje m 01001000
  2. m\,G': una palabra de tu código público 1001100100000100
  3. El error e: exactamente 2 bits a 1, en posiciones al azar (numeradas desde 0) 0010000000001000
  4. c = m\,G' + e: el texto cifrado (en rojo, los bits que el error ha cambiado) 1011100100001100

3 Descifra (con la clave privada)

Sigue el bloque 1. Solo el dueño de la clave conoce P, S y el código de Goppa.

  1. Deshaz la permutación: y = c\,P^{-1} = (m S)\,G + e P^{-1}. El error cambia de sitio pero sigue pesando 2. 0001011010000111
3.2 El algoritmo de Patterson, paso a paso

Hay que averiguar dónde está e P^{-1}. Se calcula el síndrome de y, y con él un polinomio localizador de errores \sigma cuyas raíces (en el soporte) son las posiciones del error.

  1. Síndrome S(z) = \sum_{y_j = 1} \frac{1}{z - \alpha_j} \bmod g S(z) = \alpha^{8}\,z + \alpha^{12}
  2. Inverso T(z) = S(z)^{-1} \bmod g T(z) = \alpha^{8}\,z + \alpha^{7}
  3. T(z) + z \alpha^{2}\,z + \alpha^{7}
  4. Se escribe T + z = Q_0^2 + z\,Q_1^2 y se toma la raíz cuadrada R = Q_0 + \sqrt{z}\,Q_1 \bmod g (en característica 2 siempre existe): Q_0 = \alpha^{11},\quad Q_1 = \alpha,\quad \sqrt z = \alpha^{3}\,z + \alpha^{3}
    R(z) = \alpha^{4}\,z + \alpha^{13}
  5. Euclides extendido sobre (g, R), hasta un resto de grado ≤ ⌊t/2⌋ = 1: aparecen a y b con a \equiv b R \pmod g.
    cocienteresto ruv
    z^2 + α^9·z + 110
    α^4·z + α^1301
  6. a = \alpha^{4}\,z + \alpha^{13},\quad b = 1
  7. El localizador \sigma(z) = a(z)^2 + z\,b(z)^2 \sigma(z) = \alpha^{8}\,z^{2} + z + \alpha^{11}
  8. Raíces de \sigma entre los elementos del soporte → posiciones del error: \sigma(\alpha^{5}) = 0 → posición 6\sigma(\alpha^{13}) = 0 → posición 14
  1. Se quita el error: y + e P^{-1} = (m S)\,G, una palabra del código de Goppa. 0001010010000101
  2. Como G es la identidad en el conjunto de información J, las coordenadas de la palabra en J son m S (8 bits): 00010001
  3. Y se multiplica por la inversa de S: m = (m S)\,S^{-1}. 01001000
Mensaje descifrado: Hola ✓ coincide con el original

4 Sé el atacante

Eres el atacante: solo tienes la clave pública G′ y el texto cifrado del bloque 1. El ataque de Prange elige 8 columnas al azar (un «conjunto de información»); si el error no cae en ninguna de ellas, con esas 8 columnas puedes despejar el mensaje con álgebra lineal y comprobar que lo que sobra pesa 2. Cada intento acierta con probabilidad baja; se repite hasta que sale.

Intentos esperados con estos parámetros: ≈ 15.

De juguete a real: la tabla de extrapolación

Costes estimados de los ataques de Prange y Stern y tamaños de clave, desde el juguete hasta los parámetros reales
Parámetrosn, t, kPrange: iteraciones (log₂)Prange: operaciones (log₂)Prange: tiempoStern: operaciones (log₂)Stern: tiempoClave pública, forma de 1978 (G′, k × n bits)Clave pública de Classic McEliece (T)Texto cifrado (Classic)
De juguete (el de arriba)16, 2, 82,111,7menos de 1 ms12,6 (p = 1, ℓ = 5)menos de 1 ms16 B——
McEliece 19781024, 50, 52453,681,110⁷ años63,5 (p = 3, ℓ = 27)42,4 años65,5 KiB——
mceliece3488643488, 64, 2720142,8173,610³⁵ años147,4 (p = 3, ℓ = 36)10²⁷ años1,13 MiB255 KiB96 B
mceliece4608964608, 96, 3360184,9217,410⁴⁸ años189,2 (p = 3, ℓ = 37)10³⁹ años1,85 MiB511,9 KiB156 B
mceliece66881286688, 128, 5024262,4296,310⁷² años264,8 (p = 5, ℓ = 57)10⁶² años4,01 MiB1020,5 KiB208 B
mceliece69601196960, 119, 5413263,4297,210⁷² años265,3 (p = 6, ℓ = 66)10⁶² años4,49 MiB1022,8 KiB194 B
mceliece81921288192, 128, 6528300,1334,410⁸³ años300,4 (p = 8, ℓ = 85)10⁷³ años6,38 MiB1,29 MiB208 B
  • Prange es el ataque genérico básico, no el mejor. Stern (1989) y sus sucesores lo mejoran mucho; por eso hay una columna con Stern, en un modelo sencillo y sin sus mejoras posteriores. Los parámetros reales se eligen frente a ataques todavía mejores y con modelos de coste más finos (memoria incluida), así que estas cifras son órdenes de magnitud y no el nivel de seguridad que declara Classic McEliece.
  • La lección: con parámetros de juguete, el ataque acaba al instante (pruébalo arriba). Pasar a n = 3488 o más convierte el mismo ataque en un cálculo fuera de alcance. La seguridad de McEliece es esa distancia, no un secreto del algoritmo.
  • El precio es el tamaño: la clave pública de Classic McEliece ocupa de cientos de kilobytes a más de un megabyte (en 1978 bastaban unos 65 KiB con n = 1024), pero el texto cifrado es muy corto.
  • «Clave pública de Classic McEliece» es la matriz T de la versión de Niederreiter con clave sistemática: no es exactamente la G′ de esta demo (columna anterior), que se da para comparar.

¿Y los ataques de 2025-2026?

En 2025 y 2026 se han publicado trabajos nuevos contra los códigos de Goppa binarios de Classic McEliece. Lo demostrado es un distinguidor: permite reconocer que una clave pública no es una matriz aleatoria, pero no descifra nada. Las recuperaciones de clave son heurísticas, con estimaciones de coste por debajo del nivel de seguridad declarado en el modelo de operaciones de bit (que no cobra la memoria): se ha estrechado el margen, pero no hay ningún ataque práctico. El BSI alemán desaconseja Classic McEliece para desarrollos nuevos desde el 1 de octubre de 2026.

Esta demo es el McEliece original de 1978, no Classic McEliece. Léelo con calma en el artículo, con las fuentes.