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.

PHP
require_once __DIR__ . '/core/malla.php';

Requisitos minimos

  • PHP 7.4 o superior
  • Extension sodium habilitada (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.

PHP
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).

PHP
$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'];
Nota: Si liboqs no esta disponible, ML-KEM-768 se simula generando bytes aleatorios y mezclandolos con SHA-512. El resultado tiene las mismas longitudes que ML-KEM-768 real, pero sin las propiedades criptograficas del lattice-based KEM. Para produccion, instala liboqs.

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.

PHP
$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

PHP
$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:

  1. X25519 Diffie-Hellman: Intercambio clasico con claves efimeras. Seguridad probada contra adversarios clasicos.
  2. 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).

PHP
$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)
Perfect Forward Secrecy: Cada handshake genera claves efimeras nuevas. Comprometer una sesion no afecta a sesiones pasadas ni futuras.

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.

PHP — Cifrar
$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
PHP — Descifrar
$original = pwr_malla_descifrar_paquete($paquete, $sesion);

if (is_array($original) && isset($original['error'])) {
    // Autenticacion fallida o clave incorrecta
    die($original['error']);
}
Importante: El contador de nonce se incrementa automaticamente con cada paquete cifrado. Nunca reutilices un nonce con la misma clave. Si necesitas reiniciar el contador, realiza un rekeying.

Configuraciones (WireGuard, IPsec)

WireGuard + PQC

Genera archivos de configuracion compatibles con WireGuard, incluyendo anotaciones PQC como comentarios para integracion futura.

PHP
$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.

PHP
$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.

PHP
// 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...
Recomendacion: Realizar rekeying cada hora o cada 10.000 paquetes, lo que ocurra primero. La sesion se configura con expiracion a 1 hora por defecto.

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.

PHP
$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";
}
CriterioPuntosDescripcion
Handshake hibrido25X25519 + ML-KEM-768 combinados
Cifrado de paquetes20ChaCha20 o AES-256
PFS15Perfect Forward Secrecy con claves efimeras
Rekeying10Rotacion automatica de claves
DNS seguro51.1.1.1, 9.9.9.9, 8.8.8.8
AllowedIPs restrictivo5No usar 0.0.0.0/0 sin necesidad
Preshared key5Capa adicional pre-compartida
Keepalive5PersistentKeepalive activo
MTU correcto5Entre 1280 y 1500
ML-KEM en peers5Peers con clave PQC habilitada
NotaRango
A90 – 100
B80 – 89
C65 – 79
D50 – 64
E30 – 49
F0 – 29

API de funciones

FuncionDescripcionRetorna
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

  1. El iniciador genera un par de claves efimeras X25519 y prepara la encapsulacion ML-KEM-768
  2. Se calcula el shared secret X25519 via Diffie-Hellman (sodium_crypto_scalarmult)
  3. Se encapsula un shared secret ML-KEM con la clave publica PQC del peer
  4. Ambos secrets se combinan: SHA-256(x25519_ss || mlkem_ss)
  5. Se derivan claves de sesion bidireccionales via HKDF-SHA256

Cifrado de paquetes

  1. Se construye un nonce unico: IV_base XOR contador
  2. Se cifra con ChaCha20-Poly1305 IETF (AEAD)
  3. AAD incluye tipo de paquete + contador para autenticacion
  4. 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
Referencia: El enfoque hibrido sigue las recomendaciones de NIST SP 800-227 (Initial Public Draft) para la transicion a criptografia post-cuantica, combinando algoritmos clasicos y PQC durante el periodo de migracion.