Implements NIZK (Non-Interactive Zero-Knowledge) proof protocol using Blum's Hamiltonian Cycle construction with Fiat-Shamir transformation. Features: - Complete C99 library with SHA3-256 commitments (via OpenSSL) - Graph generation with embedded trapdoor (Hamiltonian cycle) - NIZK proof generation and verification - Binary serialization for proofs, graphs, and cycles - CLI tools: zkp_keygen, zkp_prover, zkp_verifier - Comprehensive test suite (41 tests) Security properties: - Completeness: honest prover always convinces verifier - Soundness: cheater fails with probability >= 1 - 2^(-128) - Zero-Knowledge: verifier learns nothing about the secret cycle Target: OpenWrt ARM (SecuBox authentication module) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
19 KiB
19 KiB
Intégration SecuBox — Module ZKP Hamiltonien
Architecture d'intégration dans l'écosystème SecuBox
CyberMind.FR — Version 1.0
1. Positionnement dans SecuBox
1.1 Carte des modules SecuBox concernés
SecuBox (38+ modules)
│
├── secubox-core ← dépendance de base
├── secubox-auth ← MODULE PRINCIPAL CONSOMMATEUR
│ ├── zkp-hamiltonian ← CE MODULE (nouveau)
│ ├── pki-local ← remplacé partiellement
│ └── password-auth ← complété par ZKP
│
├── secubox-vpn ← intégration phase 2
├── secubox-ids ← intégration phase 3
└── secubox-luci ← interface de gestion
└── luci-app-zkp ← nouveau (dashboard LuCI)
1.2 Cas d'usage cibles
| Cas d'usage | Description | Priorité |
|---|---|---|
| Auth nœud-à-nœud | Deux routeurs prouvent mutuellement leur identité sans PKI centrale | P1 |
| Auth admin sans mot de passe | L'admin prouve qu'il possède la clé secrète (H) sans la transmettre | P1 |
| Bootstrap réseau maillé | Enrôlement d'un nouveau nœud sans autorité de certification | P2 |
| Audit de configuration | Prouver qu'une config est valide sans révéler les détails | P3 |
2. Architecture d'intégration
2.1 Vue d'ensemble
┌─────────────────────────────────────────────────────────────┐
│ SecuBox Node A (Prouveur) │
│ │
│ ┌──────────────┐ ┌──────────────┐ ┌───────────────┐ │
│ │ secubox-auth│ │zkp-hamiltonian│ │ secubox-core │ │
│ │ │───▶│ │───▶│ │ │
│ │ auth_agent │ │ zkp_prove() │ │ /dev/urandom │ │
│ │ │◀───│ │ │ libsodium │ │
│ └──────────────┘ └──────────────┘ └───────────────┘ │
│ │ │
│ │ NIZKProof (binaire sérialisé) │
└───────────┼───────────────────────────────────────────────────┘
│ réseau (UDP/TCP chiffré par secubox-vpn)
┌───────────┼───────────────────────────────────────────────────┐
│ │ SecuBox Node B (Vérifieur) │
│ ┌────────▼─────┐ ┌──────────────┐ ┌───────────────┐ │
│ │ secubox-auth│ │zkp-hamiltonian│ │ secubox-luci │ │
│ │ │───▶│ │ │ │ │
│ │ auth_verif │ │ zkp_verify() │ │ dashboard ZKP │ │
│ │ │◀───│ │ │ │ │
│ └──────────────┘ └──────────────┘ └───────────────┘ │
└─────────────────────────────────────────────────────────────-─┘
2.2 Interface avec secubox-auth
Le module secubox-auth appelle zkp-hamiltonian via une interface C bien définie et une interface de socket Unix pour les composants non-C (scripts Lua/LuCI).
/* secubox_auth_zkp.h — Interface auth ↔ ZKP */
#include "zkp_hamiltonian.h"
/* Contexte d'authentification ZKP persistant */
typedef struct {
char identity[64]; /* identifiant du nœud ("node-A") */
Graph G; /* graphe public partagé */
HamiltonianCycle H; /* clé secrète (uniquement côté prouveur) */
uint8_t G_fingerprint[32]; /* SHA3-256(G sérialisé), partagé */
bool has_secret; /* true si ce nœud est prouveur */
} ZKPAuthContext;
/* Initialisation */
int zkp_auth_init_prover(ZKPAuthContext *ctx,
const char *identity,
uint8_t n,
double extra_ratio);
int zkp_auth_init_verifier(ZKPAuthContext *ctx,
const char *identity,
const uint8_t *serialized_G,
size_t G_len);
/* Protocole */
int zkp_auth_prove(const ZKPAuthContext *ctx,
uint8_t *proof_buf,
size_t *proof_len);
int zkp_auth_verify(const ZKPAuthContext *ctx,
const uint8_t *proof_buf,
size_t proof_len);
/* Export du graphe public (à diffuser au vérifieur) */
int zkp_auth_export_public(const ZKPAuthContext *ctx,
uint8_t *buf,
size_t *len);
/* Persistance sécurisée */
int zkp_auth_save_context(const ZKPAuthContext *ctx,
const char *path); /* chiffré AES-256-GCM */
int zkp_auth_load_context(ZKPAuthContext *ctx,
const char *path,
const uint8_t *key); /* clé de déchiffrement */
3. Protocole réseau SecuBox-ZKP
3.1 Format des messages
Tous les messages sont encapsulés dans le format SecuBox standard (TLV binaire) :
┌──────────────────────────────────────────────────────────────┐
│ SecuBox Message Frame │
│ │
│ [4B] Magic = 0x5345_435A ("SECZ") │
│ [1B] Version = 0x01 │
│ [1B] Type = voir tableau ci-dessous │
│ [2B] Reserved = 0x0000 │
│ [4B] Length = longueur du payload en octets (big-endian) │
│ [32B] HMAC = HMAC-SHA3-256(header+payload, session_key) │
│ [Nb] Payload = données du message │
└──────────────────────────────────────────────────────────────┘
| Type | Valeur | Description |
|---|---|---|
ZKP_HELLO |
0x10 | Demande d'auth, envoie identité |
ZKP_GRAPH_OFFER |
0x11 | Prouveur envoie G (graphe public) |
ZKP_GRAPH_ACK |
0x12 | Vérifieur confirme réception de G |
ZKP_PROOF |
0x13 | Prouveur envoie NIZKProof |
ZKP_RESULT |
0x14 | Vérifieur envoie ACCEPT/REJECT |
ZKP_ERROR |
0xFF | Erreur protocolaire |
3.2 Séquence d'authentification complète
Prouveur (A) Vérifieur (B)
│ │
│──── ZKP_HELLO {identity_A, n} ──────────▶│
│ │ (lookup G_A dans sa DB
│ │ ou demande envoi)
│◀─── ZKP_GRAPH_OFFER? ou ZKP_GRAPH_ACK ──│
│ │
│ [si B ne connaît pas G_A] │
│──── ZKP_GRAPH_OFFER {G_sérialisé} ──────▶│
│ │ (stocke G_A,
│ │ vérifie fingerprint)
│◀─── ZKP_GRAPH_ACK {G_fingerprint} ───────│
│ │
│ [génération de la preuve NIZK] │
│ zkp_prove(G, H) → NIZKProof │
│ │
│──── ZKP_PROOF {NIZKProof_sérialisée} ───▶│
│ │ zkp_verify(G, proof)
│◀─── ZKP_RESULT {ACCEPT, timestamp} ──────│
│ │
│ [session établie] │
3.3 Gestion des timeouts et rejeu
/* Paramètres de sécurité du protocole réseau */
#define ZKP_NET_TIMEOUT_MS 5000 /* 5s max par message */
#define ZKP_NET_MAX_PROOF_SIZE (128*128*32 + 512) /* taille max NIZKProof */
#define ZKP_SESSION_NONCE_TTL_S 30 /* nonce de session périmé après 30s */
#define ZKP_MAX_AUTH_ATTEMPTS 3 /* ban temporaire après 3 échecs */
#define ZKP_BAN_DURATION_S 300 /* 5 minutes de ban */
Le session_nonce dans NIZKProof inclut un timestamp UNIX 32 bits dans ses 4 premiers octets — le vérifieur rejette toute preuve avec timestamp > 30 secondes d'écart.
4. Stockage et persistance
4.1 Arborescence des fichiers
/etc/secubox/zkp/
├── identity.conf ← configuration du nœud
├── prover/
│ ├── graph.pub ← graphe public G (partageable)
│ ├── key.enc ← cycle H chiffré (AES-256-GCM + PBKDF2)
│ └── key.pub.fingerprint ← SHA3-256(G) pour vérification rapide
└── verifier/
├── trusted/
│ ├── node-A.pub ← graphe public de node-A
│ ├── node-B.pub ← graphe public de node-B
│ └── ...
└── sessions/
└── [nonce].used ← nonces consommés (anti-rejeu, TTL 30s)
4.2 Format de la clé chiffrée (key.enc)
┌─────────────────────────────────────────────────────┐
│ ZKP Key File v1 │
│ │
│ [4B] Magic = "ZKPK" │
│ [1B] Version = 0x01 │
│ [16B] Salt = sel PBKDF2 (aléatoire) │
│ [12B] IV = nonce AES-256-GCM │
│ [4B] Iter = itérations PBKDF2 (ex: 100000) │
│ [4B] PayLen = longueur du payload chiffré │
│ [Nb] Payload = AES-256-GCM(HamiltonianCycle sér.) │
│ [16B] Tag = tag GCM │
└─────────────────────────────────────────────────────┘
Le mot de passe de déchiffrement est dérivé du mot de passe admin SecuBox via PBKDF2-SHA256. En option : déchiffrement via TPM si disponible sur le matériel.
4.3 Rotation des clés
/etc/secubox/zkp/rotate.sh
1. Générer (G_new, H_new) via zkp_keygen
2. Annoncer G_new aux nœuds pairs (ZKP_GRAPH_OFFER)
3. Période de grâce : 24h où G_old et G_new sont acceptés
4. Supprimer G_old après la période de grâce
5. Interface LuCI (luci-app-zkp)
5.1 Pages et fonctionnalités
SecuBox Dashboard
└── Authentification ZKP
├── [Onglet] État
│ ├── Statut du module (actif/inactif)
│ ├── Identité du nœud
│ ├── Fingerprint du graphe public
│ ├── Nombre d'authentifications réussies (24h)
│ ├── Nombre d'échecs (24h)
│ └── Dernière authentification (horodatage + peer)
│
├── [Onglet] Configuration
│ ├── Taille du graphe n (slider 20-80)
│ ├── Ratio arêtes leurres (0.5 - 2.0)
│ ├── Timeout réseau (ms)
│ ├── Tentatives max avant ban
│ └── Durée de ban (secondes)
│
├── [Onglet] Gestion des clés
│ ├── [Bouton] Générer nouvelle paire (G, H)
│ ├── [Bouton] Exporter graphe public G
│ ├── [Bouton] Importer graphe public (pair de confiance)
│ ├── [Bouton] Rotation des clés
│ └── Liste des pairs de confiance
│
└── [Onglet] Journal
├── Filtres : date, peer, résultat
├── Tableau des événements d'authentification
└── [Bouton] Exporter CSV
5.2 Backend UCI (Unified Configuration Interface)
# /etc/config/secubox_zkp
config zkp 'global'
option enabled '1'
option identity 'node-notre-dame-01'
option graph_n '50'
option extra_ratio '1.0'
option timeout_ms '5000'
option max_attempts '3'
option ban_duration '300'
option log_level 'info' # debug|info|warn|error
config zkp 'network'
option listen_port '7890'
option bind_addr '0.0.0.0'
option use_tls '1' # TLS par-dessus pour le transport
config trusted_peer 'node-a'
option identity 'node-a'
option graph_file '/etc/secubox/zkp/verifier/trusted/node-a.pub'
option fingerprint 'a1b2c3...'
option enabled '1'
5.3 Script UCI de génération initiale
#!/bin/sh
# /etc/secubox/zkp/init.sh
# Appelé lors du premier démarrage ou après factory reset
IDENTITY=$(uci get secubox_zkp.global.identity 2>/dev/null || hostname)
N=$(uci get secubox_zkp.global.graph_n 2>/dev/null || echo 50)
RATIO=$(uci get secubox_zkp.global.extra_ratio 2>/dev/null || echo 1.0)
mkdir -p /etc/secubox/zkp/prover
mkdir -p /etc/secubox/zkp/verifier/trusted
mkdir -p /etc/secubox/zkp/verifier/sessions
# Génération de la paire (G, H)
zkp_keygen -n "$N" -r "$RATIO" -o /etc/secubox/zkp/prover/identity \
&& logger -t secubox-zkp "Graphe généré : n=$N, ratio=$RATIO" \
|| { logger -t secubox-zkp "ERREUR : génération échouée"; exit 1; }
# Calcul du fingerprint
sha3sum /etc/secubox/zkp/prover/identity.graph \
> /etc/secubox/zkp/prover/key.pub.fingerprint
logger -t secubox-zkp "Initialisation ZKP terminée pour $IDENTITY"
6. Daemon secubox-zkpd
6.1 Rôle
Le daemon secubox-zkpd gère les connexions entrantes, maintient les sessions, applique les politiques de ban, et journalise les événements dans syslog.
6.2 Fichier de démarrage init.d
#!/bin/sh /etc/rc.common
# /etc/init.d/secubox-zkpd
START=85
STOP=15
USE_PROCD=1
NAME=secubox-zkpd
PROG=/usr/sbin/secubox-zkpd
start_service() {
local enabled identity port bind_addr
config_load secubox_zkp
config_get_bool enabled global enabled 1
[ "$enabled" -eq 0 ] && return 0
config_get identity global identity "secubox-node"
config_get port network listen_port 7890
config_get bind_addr network bind_addr "0.0.0.0"
procd_open_instance
procd_set_param command "$PROG" \
-i "$identity" \
-p "$port" \
-b "$bind_addr" \
-g /etc/secubox/zkp/prover/identity.graph \
-k /etc/secubox/zkp/prover/identity.key.enc \
-T /etc/secubox/zkp/verifier/trusted/ \
-S /etc/secubox/zkp/verifier/sessions/
procd_set_param respawn 3600 5 0
procd_set_param stdout 1
procd_set_param stderr 1
procd_set_param file /etc/config/secubox_zkp
procd_close_instance
}
reload_service() {
stop
start
}
6.3 Intégration syslog
/* Niveaux de log SecuBox-ZKP */
#define ZKP_LOG_DEBUG LOG_DEBUG
#define ZKP_LOG_INFO LOG_INFO
#define ZKP_LOG_WARN LOG_WARNING
#define ZKP_LOG_ERROR LOG_ERR
#define ZKP_LOG_AUDIT LOG_NOTICE /* toujours loggé, pour l'audit ANSSI */
/* Macro de log */
#define zkp_log(level, fmt, ...) \
syslog(level, "[secubox-zkp] " fmt, ##__VA_ARGS__)
/* Événements d'audit obligatoires (ANSSI CSPN) */
/* Toujours logger avec ZKP_LOG_AUDIT : */
/* - AUTH_SUCCESS : peer, timestamp, proof_size */
/* - AUTH_FAILURE : peer, timestamp, raison */
/* - KEY_GENERATED : n, ratio, fingerprint */
/* - KEY_ROTATED : old_fingerprint, new_fingerprint */
/* - PEER_BANNED : peer_ip, attempt_count */
/* - PEER_UNBANNED : peer_ip */
7. Tests d'intégration SecuBox
7.1 Tests sur nœud unique (simulation)
#!/bin/sh
# tests/integration/test_loopback.sh
GRAPH=/tmp/test.graph
KEY=/tmp/test.key.enc
PROOF=/tmp/test.proof
echo "=== Test 1 : Génération ==="
zkp_keygen -n 20 -r 0.5 -o /tmp/test
[ $? -eq 0 ] && echo "OK" || { echo "FAIL"; exit 1; }
echo "=== Test 2 : Preuve ==="
zkp_prover -g $GRAPH -k $KEY -o $PROOF
[ $? -eq 0 ] && echo "OK" || { echo "FAIL"; exit 1; }
echo "=== Test 3 : Vérification ==="
zkp_verifier -g $GRAPH -p $PROOF
[ $? -eq 0 ] && echo "ACCEPT OK" || { echo "REJECT - FAIL"; exit 1; }
echo "=== Test 4 : Anti-rejeu ==="
zkp_verifier -g $GRAPH -p $PROOF # deuxième fois avec même proof
[ $? -ne 0 ] && echo "OK (rejeu détecté)" || echo "FAIL (rejeu accepté)"
echo "=== Test 5 : Preuve corrompue ==="
cp $PROOF /tmp/tampered.proof
printf '\xFF' | dd of=/tmp/tampered.proof bs=1 seek=100 conv=notrunc 2>/dev/null
zkp_verifier -g $GRAPH -p /tmp/tampered.proof
[ $? -eq 1 ] && echo "REJECT OK" || echo "FAIL (corruption non détectée)"
7.2 Test deux nœuds (QEMU/netns)
# tests/integration/test_two_nodes.sh
# Requiert : ip netns, qemu ou deux VMs OpenWrt
ip netns add prover_ns
ip netns add verifier_ns
ip link add veth-p type veth peer name veth-v
ip link set veth-p netns prover_ns
ip link set veth-v netns verifier_ns
ip netns exec prover_ns ip addr add 10.0.0.1/24 dev veth-p
ip netns exec verifier_ns ip addr add 10.0.0.2/24 dev veth-v
ip netns exec prover_ns ip link set veth-p up
ip netns exec verifier_ns ip link set veth-v up
# Démarrer le vérifieur
ip netns exec verifier_ns secubox-zkpd \
-g /tmp/node-a.graph \
-T /tmp/trusted/ \
-p 7890 &
sleep 1
# Authentification depuis le prouveur
ip netns exec prover_ns zkp_client \
-g /tmp/node-a.graph \
-k /tmp/node-a.key.enc \
-H 10.0.0.2 -P 7890
echo "Résultat : $?"
8. Feuille de route d'intégration
8.1 Phases
Phase 1 — Bibliothèque standalone (4-6 semaines)
✓ zkp-hamiltonian compilé pour OpenWrt
✓ Tests unitaires passants
✓ CLI tools fonctionnels
✓ Package OpenWrt installable
Phase 2 — Intégration auth (3-4 semaines)
✓ secubox-auth utilise zkp pour auth nœud-à-nœud
✓ Protocole réseau implémenté (secubox-zkpd)
✓ UCI configuration
✓ init.d + procd
Phase 3 — Interface LuCI (2-3 semaines)
✓ luci-app-zkp dashboard
✓ Gestion des clés via interface web
✓ Journal d'authentification
✓ Import/export des graphes pairs
Phase 4 — Durcissement CSPN (ongoing)
✓ Audit des logs conformes ANSSI
✓ Tests de pénétration
✓ Documentation pour dossier CSPN
✓ Fuzz testing des parseurs réseau
8.2 Dépendances inter-modules SecuBox
zkp-hamiltonian
↑ requis par
secubox-auth (mod_zkp)
↑ requis par
secubox-vpn (auth handshake)
secubox-ids (détection bruteforce ZKP)
luci-app-zkp (interface)
secubox-audit (logs CSPN)