McEliece: esconde un mensaje entre errores
En 1978, Robert McEliece propuso cifrar con un código corrector de errores: el mensaje se codifica y se le añaden errores a propósito. Solo quien conoce el código secreto sabe quitarlos. Genera tus claves, cifra, descifra y después ponte en la piel del atacante.
Borrador: pendiente de que lo revise el autor. Esta página no aparece en Google.
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.
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.
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.
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 | α^5 | 1 | α^13 | α^9 | α^5 | α^13 | α |
| 0 | α^6 | 1 | α^11 | α^2 | α^5 | α^8 | α^9 | α^13 | α^13 | α^9 | α^8 | α^5 | α^2 | α^11 | 1 |
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
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.
| Bloque | m (8 bits) | e (peso 2) | c = mG′ + e (16 bits) |
|---|---|---|---|
01001000 | 2, 12 | 1011100100001100 | |
01101111 | 8, 10 | 1100101010101010 | |
01101100 | 8, 15 | 1001111111110101 | |
01100001 | 7, 14 | 0000000011110011 |
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
- El mensaje
m01001000 m\,G': una palabra de tu código público 1001100100000100- El error
e: exactamente 2 bits a 1, en posiciones al azar (numeradas desde 0) 0010000000001000 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.
- 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.
- Síndrome
S(z) = \sum_{y_j = 1} \frac{1}{z - \alpha_j} \bmod gS(z) = \alpha^{8}\,z + \alpha^{12} - Inverso
T(z) = S(z)^{-1} \bmod gT(z) = \alpha^{8}\,z + \alpha^{7} T(z) + z\alpha^{2}\,z + \alpha^{7}- Se escribe
T + z = Q_0^2 + z\,Q_1^2y se toma la raíz cuadradaR = 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} - Euclides extendido sobre
(g, R), hasta un resto de grado ≤ ⌊t/2⌋ = 1: aparecenaybcona \equiv b R \pmod g.cociente resto r u v z^2 + α^9·z + 1 1 0 α^4·z + α^13 0 1 a = \alpha^{4}\,z + \alpha^{13},\quad b = 1- El localizador
\sigma(z) = a(z)^2 + z\,b(z)^2\sigma(z) = \alpha^{8}\,z^{2} + z + \alpha^{11} - Raíces de
\sigmaentre los elementos del soporte → posiciones del error:\sigma(\alpha^{5}) = 0→ posición 6\sigma(\alpha^{13}) = 0→ posición 14
- Se quita el error:
y + e P^{-1} = (m S)\,G, una palabra del código de Goppa. 0001010010000101 - Como
Ges la identidad en el conjunto de informaciónJ, las coordenadas de la palabra enJsonm S(8 bits): 00010001 - Y se multiplica por la inversa de
S:m = (m S)\,S^{-1}. 01001000
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
| Parámetros | n, t, k | Prange: iteraciones (log₂) | Prange: operaciones (log₂) | Prange: tiempo | Stern: operaciones (log₂) | Stern: tiempo | Clave 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, 8 | 2,1 | 11,7 | menos de 1 ms | 12,6 (p = 1, ℓ = 5) | menos de 1 ms | 16 B | — | — |
| McEliece 1978 | 1024, 50, 524 | 53,6 | 81,1 | 10⁷ años | 63,5 (p = 3, ℓ = 27) | 42,4 años | 65,5 KiB | — | — |
| mceliece348864 | 3488, 64, 2720 | 142,8 | 173,6 | 10³⁵ años | 147,4 (p = 3, ℓ = 36) | 10²⁷ años | 1,13 MiB | 255 KiB | 96 B |
| mceliece460896 | 4608, 96, 3360 | 184,9 | 217,4 | 10⁴⁸ años | 189,2 (p = 3, ℓ = 37) | 10³⁹ años | 1,85 MiB | 511,9 KiB | 156 B |
| mceliece6688128 | 6688, 128, 5024 | 262,4 | 296,3 | 10⁷² años | 264,8 (p = 5, ℓ = 57) | 10⁶² años | 4,01 MiB | 1020,5 KiB | 208 B |
| mceliece6960119 | 6960, 119, 5413 | 263,4 | 297,2 | 10⁷² años | 265,3 (p = 6, ℓ = 66) | 10⁶² años | 4,49 MiB | 1022,8 KiB | 194 B |
| mceliece8192128 | 8192, 128, 6528 | 300,1 | 334,4 | 10⁸³ años | 300,4 (p = 8, ℓ = 85) | 10⁷³ años | 6,38 MiB | 1,29 MiB | 208 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.
Incrusta esta demo en tu web
Copia este código y pégalo en tu web, tu blog o tu aula virtual. Es gratis; solo te pedimos que dejes el pie con el enlace.
Ver cómo queda ↗Qué mirar
Con el tamaño «De juguete» (cuerpo de 16 elementos, 2 errores), cifra «Hola»: cada letra es un bloque de 8 bits. Pasa a «Mediano» y ataca: Prange tarda unos cientos de intentos. Prueba «Muy grande» y fíjate en cuánto más cuesta. Y con «McEliece 1978» comprueba que la clave pública es una matriz de más de medio megabit, y que el mismo ataque ya no termina.
Las matemáticas que hay debajo (síndrome, cuerpos finitos, códigos de Reed-Solomon, de los que los de Goppa son parientes) están en el curso:decodificación por síndrome ycódigos de Reed-Solomon. El artículo completo, con el estado de la seguridad y sus fuentes: cómo funciona el cifrado de McEliece. Para comparar con el cifrado de clave pública más usado: RSA paso a paso.
Preguntas frecuentes
¿Cómo funciona el cifrado de McEliece, en una frase?
Se elige un código corrector de errores que sabes decodificar (un código de Goppa), se disfraza multiplicando su matriz por otras dos (S y P) para que parezca uno cualquiera, y se publica el disfraz. Cifrar es codificar el mensaje con el código público y añadir a propósito exactamente t errores; descifrar es quitarlos con el código secreto, que es el único que sabe corregirlos.
¿Por qué no se puede descifrar sin la clave privada?
Quien solo tiene la clave pública necesita decodificar un código lineal sin estructura visible, y ese problema es difícil en general: los mejores algoritmos genéricos (Prange, Stern y sus sucesores) tardan un tiempo exponencial en n. En la demo, con parámetros de juguete, lo ves acabar al instante; con los parámetros reales, no.
¿Por qué hay que añadir exactamente t errores?
Un código de Goppa de grado t corrige hasta t errores. Con menos, el cifrado seguiría siendo descifrable, pero un ataque tendría menos que buscar; con más de t, ni siquiera el dueño de la clave podría decodificar. La demo te deja comprobarlo: elige a mano más de t errores y el descifrado falla (o, peor, se equivoca sin avisar).
¿Es esto Classic McEliece, el de los estándares?
No exactamente. Esta demo es el esquema original de McEliece (1978). Classic McEliece usa la versión dual de Niederreiter (1986), como mecanismo de encapsulación de claves, con la clave pública en forma sistemática. Comparten el mismo código de Goppa y por eso los tamaños y costes de la tabla son los suyos.
¿Se ha roto McEliece?
No: no se conoce ningún ataque práctico contra los parámetros reales. En 2025 y 2026 se han publicado trabajos nuevos (un distinguidor demostrado y recuperaciones de clave heurísticas con estimaciones por debajo del nivel declarado en el modelo de operaciones de bit), de modo que se ha estrechado el margen de seguridad, y el BSI alemán lo desaconseja para desarrollos nuevos desde el 1 de octubre de 2026. Las fuentes, en el artículo.
¿Mis claves o mensajes se envían a algún sitio?
No. Todo se calcula en tu navegador. El enlace de «Copiar enlace» lleva solo el tamaño del código, la semilla y el mensaje, nada más.
Cómo citar esta página
Fernando Hernando (2026). Cifrado de McEliece paso a paso [Herramienta web], versión del 22 de octubre de 2026. El bit perdido. https://elbitperdido.com/herramientas/mceliece
@misc{hernando2026mceliece,
author = {Fernando Hernando},
title = {Cifrado de McEliece paso a paso},
year = {2026},
howpublished = {El bit perdido},
url = {https://elbitperdido.com/herramientas/mceliece},
note = {Herramienta web, versión del 22 de octubre de 2026}
}