PWR Malla
Motor VPN post-cuantico con handshake hibrido X25519 + ML-KEM-768. Genera configuraciones WireGuard e IPsec con anotaciones PQC, gestiona peers y cifra/descifra paquetes con ChaCha20-Poly1305. PHP puro, sin dependencias externas.
Instalacion
Malla es un unico archivo PHP. Copialo a tu proyecto e incluyelo donde necesites funcionalidad VPN post-cuantica.
require_once __DIR__ . '/core/malla.php';
Requisitos minimos
- PHP 7.4 o superior
- Extension
sodiumhabilitada (incluida en PHP 7.2+) - Opcional: liboqs para ML-KEM-768 nativo (sin ella, se simula con SHA-512)
Uso rapido
En cinco pasos: generar claves, crear peer, handshake, cifrar y descifrar.
require_once 'core/malla.php';
// 1. Generar claves hibridas
$claves = pwr_malla_generar_claves();
// 2. Crear un peer
$peer = pwr_malla_crear_peer(
'Servidor Madrid',
'203.0.113.1:51820',
$pk_remota
);
// 3. Handshake hibrido (X25519 + ML-KEM-768)
$sesion = pwr_malla_handshake($peer);
// 4. Cifrar un paquete
$paquete = pwr_malla_cifrar_paquete($datos, $sesion);
// 5. Descifrar
$original = pwr_malla_descifrar_paquete($paquete, $sesion);
Generar claves
pwr_malla_generar_claves() genera un par de claves hibrido:
un componente clasico X25519 (via libsodium) y un componente post-cuantico
ML-KEM-768 (nativo con liboqs o simulado con SHA-512).
$claves = pwr_malla_generar_claves();
// Componente clasico X25519
$x25519_pk = $claves['x25519']['publica']; // 32 bytes
$x25519_sk = $claves['x25519']['secreta']; // 32 bytes
// Componente PQC ML-KEM-768
$mlkem_pk = $claves['mlkem']['publica']; // 1184 bytes
$mlkem_sk = $claves['mlkem']['secreta']; // 2400 bytes
$nativo = $claves['mlkem']['nativo']; // true si liboqs
// Huella publica combinada (16 hex chars)
$huella = $claves['huella'];
Peers
Un peer es un nodo remoto de la malla VPN. Cada peer tiene un endpoint, clave publica y opcionalmente clave ML-KEM y preshared key.
$peer = pwr_malla_crear_peer(
'Servidor Madrid', // Nombre descriptivo
'203.0.113.1:51820', // Endpoint IP:Puerto
$pk_remota, // Clave publica X25519 (32 bytes)
[
'mlkem_pk_remota' => $mlkem_pk, // Opcional: clave ML-KEM
'preshared_key' => $psk, // Opcional: PSK adicional
'allowed_ips' => ['10.0.0.0/24'],
'keepalive' => 25,
'dns' => ['1.1.1.1'],
'mtu' => 1420,
]
);
Listar peers
$lista = pwr_malla_peers($config);
foreach ($lista as $p) {
echo $p['nombre'] . ' — ' . $p['endpoint'] . "\n";
}
Handshake hibrido (X25519 + ML-KEM-768)
El handshake combina dos intercambios de claves en paralelo:
- X25519 Diffie-Hellman: Intercambio clasico con claves efimeras. Seguridad probada contra adversarios clasicos.
- ML-KEM-768 KEM: Encapsulacion de clave basada en lattices (NIST FIPS 203). Resistente a ataques cuanticos.
El shared secret final es SHA-256(x25519_ss || mlkem_ss),
combinando ambos componentes. Si cualquiera de los dos resiste, la conexion
permanece segura (defensa en profundidad).
$sesion = pwr_malla_handshake($peer);
// La sesion contiene:
$sesion['clave_tx'] // Clave cifrado TX (32 bytes)
$sesion['clave_rx'] // Clave cifrado RX (32 bytes)
$sesion['clave_auth'] // Clave autenticacion (32 bytes)
$sesion['iv_base'] // IV base para nonces (12 bytes)
$sesion['estado'] // 'establecido'
$sesion['expira'] // Timestamp de expiracion
$sesion['shared_secret'] // Secret combinado (32 bytes)
Cifrado de paquetes
Los paquetes se cifran con ChaCha20-Poly1305 IETF (RFC 7539). El nonce se construye haciendo XOR del IV base con un contador secuencial, garantizando que nunca se repite.
$paquete = pwr_malla_cifrar_paquete($datos, $sesion);
// El paquete contiene:
$paquete['ciphertext'] // Datos cifrados + tag Poly1305
$paquete['nonce'] // Nonce de 12 bytes
$paquete['contador'] // Numero de secuencia
$paquete['aad'] // Datos adicionales autenticados
$original = pwr_malla_descifrar_paquete($paquete, $sesion);
if (is_array($original) && isset($original['error'])) {
// Autenticacion fallida o clave incorrecta
die($original['error']);
}
Configuraciones (WireGuard, IPsec)
WireGuard + PQC
Genera archivos de configuracion compatibles con WireGuard, incluyendo anotaciones PQC como comentarios para integracion futura.
$config = pwr_malla_generar_config_wireguard([
'sk_local' => $claves['x25519']['secreta'],
'direccion' => '10.0.0.1/24',
'dns' => '1.1.1.1, 9.9.9.9',
'listen_port' => 51820,
'peers' => [$peer1, $peer2],
]);
file_put_contents('wg0.conf', $config);
IPsec / strongSwan + ML-KEM
Genera configuracion strongSwan con propuestas IKEv2 que incluyen ML-KEM-768 como KEM post-cuantico hibrido.
$ipsec = pwr_malla_generar_config_ipsec([
'nombre' => 'oficina-madrid-bcn',
'local_ip' => '192.168.1.1',
'remote_ip' => '192.168.2.1',
'local_subnet' => '10.10.0.0/24',
'remote_subnet' => '10.20.0.0/24',
]);
Rekeying
La rotacion de claves mezcla el shared secret anterior con entropia fresca para derivar nuevas claves de sesion sin necesidad de un handshake completo.
// Rotar claves de sesion
pwr_malla_rotar_claves($sesion);
// Verificar estado
$estado = pwr_malla_estado($sesion);
echo $estado['estado']; // 'establecido'
echo $sesion['rekeying_count']; // 1, 2, 3...
Scoring
Evalua la seguridad de una configuracion VPN en 10 criterios y asigna una puntuacion de 0 a 100 con nota de A a F.
$score = pwr_malla_scoring($config);
echo $score['nota']; // 'A', 'B', 'C'...
echo $score['puntos']; // 85
echo $score['max_puntos']; // 100
foreach ($score['detalles'] as $d) {
echo $d['check'] . ': ' . $d['estado'] . "\n";
}
| Criterio | Puntos | Descripcion |
|---|---|---|
| Handshake hibrido | 25 | X25519 + ML-KEM-768 combinados |
| Cifrado de paquetes | 20 | ChaCha20 o AES-256 |
| PFS | 15 | Perfect Forward Secrecy con claves efimeras |
| Rekeying | 10 | Rotacion automatica de claves |
| DNS seguro | 5 | 1.1.1.1, 9.9.9.9, 8.8.8.8 |
| AllowedIPs restrictivo | 5 | No usar 0.0.0.0/0 sin necesidad |
| Preshared key | 5 | Capa adicional pre-compartida |
| Keepalive | 5 | PersistentKeepalive activo |
| MTU correcto | 5 | Entre 1280 y 1500 |
| ML-KEM en peers | 5 | Peers con clave PQC habilitada |
| Nota | Rango |
|---|---|
| A | 90 – 100 |
| B | 80 – 89 |
| C | 65 – 79 |
| D | 50 – 64 |
| E | 30 – 49 |
| F | 0 – 29 |
API de funciones
| Funcion | Descripcion | Retorna |
|---|---|---|
pwr_malla_info() |
Informacion del modulo | array |
pwr_malla_generar_claves() |
Genera par de claves hibrido X25519 + ML-KEM-768 | array |
pwr_malla_crear_peer($nombre, $endpoint, $pk, $opts) |
Crea configuracion de peer remoto | array |
pwr_malla_handshake($peer) |
Realiza handshake hibrido X25519 + ML-KEM | array (sesion) |
pwr_malla_derivar_claves_sesion($secret) |
Deriva claves de sesion via HKDF-SHA256 | array |
pwr_malla_cifrar_paquete($datos, &$sesion) |
Cifra paquete con ChaCha20-Poly1305 | array |
pwr_malla_descifrar_paquete($paq, $sesion) |
Descifra paquete | string o array error |
pwr_malla_generar_config_wireguard($params) |
Genera config WireGuard con anotaciones PQC | string |
pwr_malla_generar_config_ipsec($params) |
Genera config strongSwan/IPsec con ML-KEM | string |
pwr_malla_estado($sesion) |
Estado actual de la sesion VPN | array |
pwr_malla_rotar_claves(&$sesion) |
Rekeying: rota claves de sesion | array |
pwr_malla_peers($config) |
Lista peers configurados | array |
pwr_malla_scoring($config) |
Evalua seguridad de la config (A-F) | array |
Arquitectura
PWR Malla implementa un modelo VPN hibrido clasico-PQC inspirado en WireGuard pero con proteccion contra amenazas cuanticas.
Flujo del handshake
- El iniciador genera un par de claves efimeras X25519 y prepara la encapsulacion ML-KEM-768
- Se calcula el shared secret X25519 via Diffie-Hellman (
sodium_crypto_scalarmult) - Se encapsula un shared secret ML-KEM con la clave publica PQC del peer
- Ambos secrets se combinan:
SHA-256(x25519_ss || mlkem_ss) - Se derivan claves de sesion bidireccionales via HKDF-SHA256
Cifrado de paquetes
- Se construye un nonce unico:
IV_base XOR contador - Se cifra con ChaCha20-Poly1305 IETF (AEAD)
- AAD incluye tipo de paquete + contador para autenticacion
- El contador se incrementa automaticamente (nunca se reutiliza un nonce)
Modelo de seguridad
- Contra adversarios clasicos: X25519 DH proporciona seguridad ECDH estandar
- Contra adversarios cuanticos: ML-KEM-768 (NIST FIPS 203) resiste ataques con Shor
- Defensa en profundidad: Si uno de los dos mecanismos se rompe, el otro mantiene la seguridad
- PFS: Claves efimeras por handshake, rekeying periodico
- AEAD: ChaCha20-Poly1305 proporciona confidencialidad e integridad