#set page(margin: (top: 2cm, bottom: 2cm, left: 2.5cm, right: 2.5cm)) #set text(font: "New Computer Modern", size: 11pt) #set heading(numbering: "1.1.1") #show heading: it => { it v(0.5em) } #show link: underline #align(center)[ = Système de Vote Électronique Sécurisé == Avec Cryptographie Post-Quantique Hybride Rapport Technique et Scientifique *EPITA - Cryptographie Industrielle Avancée* \ *Novembre 2025* \ *CIA Team* ] #pagebreak() = Résumé Exécutif Ce rapport documente la conception et l'implémentation d'un *prototype fonctionnel* d'un système de vote électronique sécurisé. Le système applique les principes fondamentaux de la cryptographie pour adresser les défis spécifiques du vote en ligne : - *Fraude* : Prévention de modification/double-vote via blockchain - *Intimidation* : Confidentialité des votes via chiffrement homomorphe - *Anonymat* : Séparation entre identité et bulletin de vote Les principales contributions : - Cryptographie *post-quantique hybride* (NIST FIPS 203/204/205) - Chiffrement ElGamal avec *addition homomorphe* pour dépouillement sécurisé - Signatures *hybrides RSA-PSS + Dilithium* (quantum-resistant) - Architecture *blockchain* pour immuabilité - Déploiement *Docker autonome* et reproductible #pagebreak() = 1. Introduction == 1.1 Contexte et Motivation Les systèmes de vote électronique doivent résoudre plusieurs défis de sécurité interdépendants : 1. *Fraude Électorale* : Modification des votes, double-vote, forgerie 2. *Intimidation/Coercion* : Personne ne doit pouvoir forcer l'électeur à voter d'une certaine façon 3. *Anonymat* : Séparation entre identité du votant et son choix 4. *Intégrité* : Les votes ne doivent pas pouvoir être modifiés après soumission 5. *Immuabilité* : Audit trail complet et vérifiable = 2 Architecture et Conception du Système == 2.1 Vue Globale L'architecture suit un modèle Client/Serveur + Blockchain : ``` ┌─────────────────────────────────────────────┐ │ Frontend Web (Next.js) │ │ - Interface d'authentification │ │ - Sélection du candidat │ │ - Chiffrement du vote │ └──────────────┬────────────────────────────┘ │ HTTPS/REST JSON ┌──────────────▼────────────────────────────┐ │ Backend API (FastAPI) │ │ - Authentication JWT │ │ - Validation et chiffrement hybride │ │ - Signatures RSA + Dilithium │ │ - Gestion blockchain │ └──┬─────────────────────────────┬──────────┘ │ │ ┌──▼──────────┐ ┌────────▼──────────┐ │ MariaDB │ │ Blockchain (PoA) │ │ Voters │ │ - Vote blocks │ │ Elections │ │ - Validators │ │ Votes │ │ - PoA consensus │ └─────────────┘ └───────────────────┘ ``` == 2.2 Composants Principaux === Frontend (Next.js 15 + React 18) *Responsabilités* : - Interface utilisateur responsive - Authentification (login/register) - Sélection de candidat - Visualisation des résultats *Technologies* : - Next.js 15 pour server-side rendering - React 18 avec hooks - TypeScript pour type safety - Tailwind CSS pour le design === Backend (FastAPI + Python 3.12) *Responsabilités* : - Authentification JWT - Gestion des élections - Chiffrement hybride (ElGamal + Kyber) - Signatures hybrides (RSA + Dilithium FIPS 204) - Stockage blockchain des votes *Endpoints clés* : - `POST /api/auth/register` - Inscription avec génération clés PQC - `POST /api/auth/login` - Authentification - `GET /api/elections/active` - Élection active - `POST /api/votes/submit` - Soumission vote signé+chiffré - `GET /api/elections/{id}/results` - Résultats === Base de Données (MariaDB) *Schéma* : - Voters : Électeurs avec hachage bcrypt - Elections : Configurations avec paramètres ElGamal - Candidates : Options de vote - Votes : Bulletins chiffrés (stockage séparé pour confidentialité) === Blockchain (Python + PoA Validators) *Composants* : - Blockchain locale : stockage immuable des votes - Signature Dilithium : authenticité de chaque bloc - Chaîne de hachage SHA-256 : intégrité - PoA Validators : consensus distribué optionnel #pagebreak() = 3 Cryptographie Post-Quantique Hybride == 3.1 Motivation et Stratégie *Menace Quantique* : Les ordinateurs quantiques théoriques cassent RSA/ElGamal classiques en temps polynomial (algorithme de Shor). *Defense-in-Depth* : Combinaison classique + post-quantique : - Si RSA cassé → Dilithium (FIPS 204) reste sûr - Si Dilithium cassé → RSA classique reste sûr - Aucun point de défaillance unique cryptographique == 3.2 Composants Certifiés NIST === Signatures Hybrides : RSA-PSS + ML-DSA-65 (Dilithium) *RSA-PSS (Classique)* : - Taille clé : 2 048 bits - Sécurité : ~128 bits classique - Algorithme établi depuis 1977 *ML-DSA-65 (FIPS 204)* : - Basé sur problème LWE (Learning With Errors) - Taille signature : 2 420 bytes - Sécurité : 192-bit post-quantique - Finalisé par NIST : 2024 *Processus de signature hybride* : ``` message = vote_data sig_rsa = RSA-PSS.sign(message, rsa_private_key) sig_dilithium = ML-DSA-65.sign(message, dilithium_private_key) # Vérification : LES DEUX doivent être valides assert RSA-PSS.verify(message, sig_rsa, rsa_public_key) assert ML-DSA-65.verify(message, sig_dilithium, dilithium_public_key) ``` === Chiffrement Hybride : ElGamal + ML-KEM-768 (Kyber) *ElGamal (Classique)* : - Groupe : $Z_p^*$ avec premier $p$ - Propriété : Addition homomorphe - Sécurité : IND-CPA sémantiquement sûr *ML-KEM-768 (FIPS 203)* : - Basé sur problème LWE - Taille ciphertext : 1 088 bytes - Sécurité : 192-bit post-quantique - Finalisé par NIST : 2024 *Processus d'encapsulation hybride* : ``` # Kyber : Key Encapsulation Mechanism kyber_ct, kyber_ss = ML-KEM-768.encap(kyber_public_key) # ElGamal : Classic encryption eg_ct = ElGamal.encrypt(message, elgamal_public_key) # Fusion des secrets final_key = SHA-256(kyber_ss || eg_ss) # Chiffrement symétrique du bulletin encrypted_ballot = AES-256-GCM.encrypt(final_key, ballot) ``` === Hachage : SHA-256 - Sortie : 256 bits - Résistant quantique pour preimage - Quantum computer : ~$2^{128}$ opérations pour collision (Grover) - Toujours infaisable pratiquement == 3.3 Propriétés Homomorphes d'ElGamal *Définition* : Chiffrement addif homomorphe = opérations sur ciphertexts → opérations sur plaintexts. Pour ElGamal avec groupe multiplicatif $G$ : $ E(m_1) times E(m_2) = E(m_1 + m_2) $ *Preuve* : ``` E(m₁) = (c₁, c₂) = (g^r₁, m₁ · h^r₁) E(m₂) = (c₁', c₂') = (g^r₂, m₂ · h^r₂) E(m₁) × E(m₂) = (g^r₁ · g^r₂, m₁·h^r₁ · m₂·h^r₂) = (g^(r₁+r₂), (m₁+m₂)·h^(r₁+r₂)) = E(m₁ + m₂) ✓ ``` *Application au vote* : ``` Vote binaire : chaque candidat reçoit 0 ou 1 E(total_candidat_A) = E(1) × E(0) × ... × E(1) = E(1 + 0 + ... + 1) = E(nombre de votes pour A) Dépouillement : 1. Récupérer tous E(vote_i) de la blockchain 2. Calculer E(total) = ∏ E(vote_i) 3. Déchiffrer UNE SEULE FOIS : total = Dec(E(total)) 4. Publier résultats anonymes ``` #pagebreak() = 4 Flux Complet du Processus de Vote == 4.1 Phase 1 : Inscription ``` Électeur : Entre email, nom, CNI, mot de passe ↓ Backend : 1. Vérifier email unique 2. Générer clés hybrides : - RSA 2048 (signature) - ML-DSA-65/Dilithium (signature) - ElGamal (chiffrement) - ML-KEM-768/Kyber (KEM) 3. Hacher mot de passe avec bcrypt 4. Enregistrer dans BD ↓ Frontend : Afficher confir mation et rediriger vers login ``` == 4.2 Phase 2 : Authentification ``` Électeur : Entrer email + mot de passe ↓ Backend : 1. Vérifier email existe 2. Vérifier password avec bcrypt 3. Générer JWT token (30 min expiration) 4. Retourner token ↓ Frontend : Stocker token, rediriger vers élections ``` == 4.3 Phase 3 : Affichage de l'Élection ``` Frontend : GET /api/elections/active ↓ Backend : 1. Vérifier JWT valide et non expiré 2. Vérifier électeur authentifié 3. Récupérer élection active depuis BD 4. Récupérer candidats ↓ Frontend : Afficher liste candidats ``` == 4.4 Phase 4 : Soumission du Vote ``` Électeur : Sélectionner candidat A ↓ Frontend : 1. Créer ballot = {election_id, candidat_id, timestamp} 2. Hacher : ballot_hash = SHA-256(ballot) 3. Signer avec RSA + Dilithium 4. Chiffrer avec ElGamal + Kyber ↓ Backend (POST /api/votes/submit) : 1. Vérifier JWT 2. Vérifier pas déjà voté (check voters.has_voted) 3. Vérifier signature RSA valide 4. Vérifier signature Dilithium valide 5. Vérifier élection active 6. Ajouter bloc blockchain : Block { index: len(chain) + 1 prev_hash: SHA-256(previous_block) encrypted_vote: vote_chiffré signature: DILITHIUM.sign(block_hash) } 7. Marquer voters.has_voted = True 8. Retourner confirmation ↓ Frontend : Afficher confirmation avec ballot_hash ``` == 4.5 Phase 5 : Dépouillement Sécurisé ``` Admin : Demander résultats après clôture ↓ Backend : 1. Récupérer tous votes chiffrés de blockchain 2. Addition homomorphe : E(total_A) = ∏ E(vote_candidat_A_i) 3. Déchiffrer : total_A = Dec_sk(E(total_A)) 4. Publier résultats anonymes ↓ Frontend : Afficher résultats (graphiques) ``` == 4.6 Phase 6 : Vérification et Audit ``` Vérificateur : Audit complet 1. Récupérer blockchain complète 2. Vérifier intégrité chaîne : for each block in chain: assert block.block_hash == SHA-256(block_content) assert DILITHIUM.verify(block.signature) assert block.prev_hash == previous.block_hash 3. Compter votes : len(chain) - 1 (exclude genesis) 4. Vérifier chaque électeur n'a voté qu'une fois 5. Publier rapport d'audit ↓ Result : Élection vérifiée et trustworthy ``` #pagebreak() = 5 Propriétés de Sécurité Formelles == 5.1 Confidentialité du Vote *Définition* : Adversaire ne peut déterminer pour qui a voté un électeur. *Garantie* : ElGamal sémantiquement sûr (IND-CPA) - Vote chiffré : $E(v) = (c_1, c_2)$ - Même plaintext produit différents ciphertexts (probabiliste) - Sans clé privée $x$ : impossible de déchiffrer *Protection* : Kyber (post-quantique) renforce cette propriété contre ordinateurs quantiques. == 5.2 Intégrité des Votes *Définition* : Vote ne peut être modifié après soumission. *Garantie* : Blockchain avec chaîne de hachage SHA-256 ``` Block_0 → Block_1 → Block_2 → ... → Block_n Si attaquant modifie Block_k: 1. block_hash[Block_k] change 2. prev_hash[Block_{k+1}] != block_hash[Block_k] 3. Tous blocs suivants invalides 4. Détection certaine lors vérification ``` *Protection* : Signature Dilithium sur chaque bloc. == 5.3 Non-Répudiation *Définition* : Électeur ne peut nier avoir voté. *Garantie* : Signatures hybrides RSA + Dilithium ``` Vote signé avec DEUX signatures : sig_rsa = RSA-PSS.sign(ballot, rsa_sk) sig_dilithium = ML-DSA-65.sign(ballot, dilithium_sk) Électeur prétend ne pas avoir signé: → Produit clés différentes → Signatures RSA ou Dilithium échouent → Contradiction prouvable ``` == 5.4 Authentification du Votant *Définition* : Vote vient d'électeur authentifié. *Garantie* : JWT + bcrypt ``` 1. Électeur login → reçoit JWT signé(SECRET_KEY, {voter_id, exp}) 2. Vote includs Authorization: Bearer 3. Backend vérifie : - JWT signature valide - JWT non expiré - voter_id du JWT = voter du vote ``` == 5.5 Anti-Coercion (Partiel) *Définition* : Électeur ne peut prouver son vote à un tiers. *Approche* : - Votes chiffrés : attaquant ne peut vérifier - Preuves ZK non-transférables : secret pas révélé - Backend seul connaît secrets de déchiffrement *Limitation* : Si attaquant observe l'écran directement → nécessite isolement physique. #pagebreak() = 6 Analyse des Menaces et Mitigations == 6.1 Fraude Électorale *Menace* : Modification des votes après soumission *Mitigation* : - Chaîne de hachage SHA-256 : modification d'un vote invalide toute la chaîne - Signature Dilithium : bloc non-signable sans clé privée - Vérification publique possible - Addition homomorphe détecterait votes modifiés *Risque résiduel* : Faible (détection certaine) == 6.2 Double-Vote *Menace* : Même électeur vote deux fois *Mitigation* : - Constraint unique (voter_id, election_id) - voters.has_voted flag - Vérification backend avant enregistrement - Blockchain enregistre une fois *Risque résiduel* : Aucun (prévention garantie) == 6.3 Usurpation d'Identité *Menace* : Attaquant vote au nom d'autrui *Mitigation* : - Authentification JWT forte - Vérification identité à l'inscription (CNI) - Mot de passe bcrypt - Tokens non-transférables *Risque résiduel* : Faible (si acces device de l'électeur) == 6.4 Intimidation / Coercion *Menace* : Tiers force électeur à voter d'une certaine façon *Mitigation (partielle)* : - Vote chiffré : coerciteur ne peut vérifier - Votes anonymes : liaison identité-bulletin impossible - Preuves ZK : électeur ne peut transférer preuve du vote *Risque résiduel* : Modéré (si observation directe de l'écran) - Mitigations complémentaires : isolement physique du bureau, caméras (si légal) == 6.5 Attaque Administrateur *Menace* : Admin avec accès BD compromet tout *Mitigation* : - Principle of least privilege - Audit logs séparés - Chiffrement données sensibles - Secrets dans env vars, pas en code *Risque résiduel* : Élevé si BD compromise - Mitigation : infrastructure sécurisée, backups chiffrés == 6.6 Attaque Quantique Future *Menace* : Ordinateur quantique décrypte RSA/ElGamal *Mitigation* : - Chiffrement hybride ElGamal + Kyber - Signatures hybrides RSA + Dilithium - Hachage SHA-256 (quantum-resistant pour preimage) *Résultat* : Sécurité maintenue si au moins l'un des systèmes reste sûr == 6.7 Injection SQL *Menace* : Exploit requête SQL malveillante *Mitigation* : - SQLAlchemy ORM : prévient injections - Prepared statements implicites - Type hints + validation Pydantic *Risque résiduel* : Minimal #pagebreak() = 7 Implémentation Technique == 7.1 Stack Technologique === Backend *Python 3.12* - Type hints modernes (PEP 484, 585) - Performance améliorée (3.12+ optimisations) - Async/await natif *FastAPI* - Framework moderne ASGI - Documentation auto (OpenAPI/Swagger) - Validation Pydantic intégrée - Performance compétitive (bench: 3-5x plus rapide que Django) *SQLAlchemy 2.0* - ORM robuste - Type-safe queries - Support transactions ACID *liboqs-python* - Bindings pour librairie C liboqs - Algorithmes NIST certifiés - ML-DSA-65 (Dilithium), ML-KEM-768 (Kyber) === Frontend *Next.js 15* - SSR (Server-Side Rendering) : sécurité - Static generation quand possible - Image optimization automatique - API routes intégrées *React 18* - Hooks modernes - Concurrent features - Strict mode détecte problèmes *TypeScript* - Type safety complet - Better IDE support - Documentation via types *Tailwind CSS + Shadcn* - Utility-first CSS - Thème cohérent - Accessible par défaut === Infrastructure *Docker Compose* - Orchestration local/dev - Volumes persistants - Networks isolation - Health checks *MariaDB* - ACID transactions - Replication support - Performant - Compatible MySQL == 7.2 Architecture de Fichiers ``` backend/ ├── main.py # Application FastAPI ├── config.py # Configuration (env vars) ├── models.py # SQLAlchemy models ├── schemas.py # Pydantic schemas ├── auth.py # Authentification JWT ├── database.py # Connexion BD ├── services.py # Logique métier ├── blockchain.py # Blockchain local ├── blockchain_elections.py # Elections blockchain ├── blockchain_client.py # Client PoA ├── init_blockchain.py # Initialisation blockchain ├── crypto/ │ ├── pqc_hybrid.py # Crypto post-quantique hybride │ ├── encryption.py # ElGamal + AES │ ├── signatures.py # RSA-PSS │ ├── hashing.py # SHA-256 │ └── zk_proofs.py # Preuves ZK └── routes/ ├── auth.py # /api/auth/* ├── elections.py # /api/elections/* └── votes.py # /api/votes/* ``` == 7.3 Endpoints API | Endpoint | Méthode | Description | |----------|---------|-------------| | `/api/auth/register` | POST | Inscription + génération clés | | `/api/auth/login` | POST | Authentification | | `/api/auth/profile` | GET | Profil électeur | | `/api/elections/active` | GET | Élection courante | | `/api/elections/{id}` | GET | Détails élection | | `/api/elections/{id}/candidates` | GET | Candidats | | `/api/votes/submit` | POST | Soumission vote | | `/api/elections/{id}/results` | GET | Résultats | | `/api/blockchain/votes` | GET | Blockchain complète | | `/api/blockchain/verify` | POST | Vérifier intégrité | #pagebreak() = 8 Tests et Validation == 8.1 Suite de Tests === Tests Unitaires Cryptographiques *ElGamal* (`test_crypto.py`) : ``` ✓ test_keygen : Génération clés valides ✓ test_encrypt_decrypt : Chiffrement/déchiffrement ✓ test_semantic_security : Deux chiffrements différents ✓ test_homomorphic_addition : Addition votes chiffrés ``` *Signatures* : ``` ✓ test_sign_verify : Signature/vérification ✓ test_invalid_signature : Détection forgerie ``` *Blockchain* (`test_blockchain.py`) : ``` ✓ test_blockchain_integrity : Chaîne valide ✓ test_tamper_detection : Modification détectée ✓ test_genesis_block : Bloc 0 correct ``` === Tests d'Intégration *Flux complet* (`test_api_fixes.py`) : ``` ✓ Register → Login → Get Election → Vote → Results ✓ Double vote rejection ✓ Signature verification ``` == 8.2 Validation des Propriétés *Confidentialité* : ``` PASS : Vote chiffré non lisible sans clé PASS : Homomorphisme préserve confidentialité ``` *Intégrité* : ``` PASS : Modification blockchain détectée PASS : Chaîne valide si tous blocs OK ``` *Non-Répudiation* : ``` PASS : Signature impossible sans clé privée PASS : Clé privée secret ultime ``` = 9 Déploiement == 9.1 Instructions Docker ```bash # Construire docker-compose build # Lancer docker-compose up -d # Vérifier docker-compose ps # Logs docker-compose logs -f backend # Accéder Frontend : http://localhost:3000 API docs : http://localhost:8000/docs DB : localhost:3306 ``` == 9.2 Configuration Production - Variables d'environnement sécurisées - HTTPS obligatoire (Let's Encrypt) - Secrets dans `.env` chiffrés - Nginx reverse proxy - Backups automatiques BD - Monitoring (Prometheus/Grafana optionnel) #pagebreak() = 10 Limitations et Améliorations Futures == 10.1 Limitations Actuelles 1. *Blockchain locale* : Pas de vraie distribution (PoA optionnel) 2. *Anonymat limité* : Pas de mix networks 3. *Pas de TPM* : Clés stockées software 4. *Identité* : Demo sans vérification réelle == 10.2 Améliorations Possibles *Court terme* : - Consensus PoA complet - Audit de sécurité externe - Tests de charge *Moyen terme* : - Intégration mix networks - Preuves ZK avancées - Frontend mobile (React Native) *Long terme* : - Blockchain publique (Ethereum) - Chiffrement homomorphe complet (FHE) - Standards internationaux (OASIS) #pagebreak() = 11 Conclusion == 11.1 Réalisations ✓ Implémentation cryptographique correcte (ElGamal, RSA, Dilithium, Kyber) ✓ Architecture distribuée avec blockchain ✓ Déploiement Docker autonome ✓ Propriétés de sécurité formelles ✓ Tests complets ✓ Documentation détaillée == 11.2 Conformité Exigences ✓ Code source complet et fonctionnel ✓ Cryptographie post-quantique hybride NIST ✓ Déploiement autonome Docker ✓ Rapport technique & scientifique ✓ Architecture adresse fraude, intimidation, anonymat ✓ Flux utilisateur complet : inscription → vote → résultats == 11.3 Contributions Scientifiques 1. Chiffrement homomorphe appliqué au vote 2. Signatures hybrides pour quantum-resistance 3. Blockchain avec Dilithium pour immuabilité 4. Defense-in-depth cryptographique == 11.4 Perspectives Ce prototype démontre la faisabilité technique d'un système de vote électronique sécurisé et quantum-resistant. Les perspectives incluent : - Audit externe - Déploiement production avec haute disponibilité - Standards ouverts et certification - Intégration infrastructure gouvernementale --- *Rapport généré : Novembre 2025* *Système : E-Voting Post-Quantum v0.1* *Auteurs : CIA Team* - Vérification d'unicité des votes - Vérification d'intégrité de la BD == 9.3 Scénarios de Sécurité - Attaque par replay ❌ (unique voter+election) - Double vote ❌ (contrainte BD) - Modification de vote ❌ (chiffrement) - Intimdation ❌ (anonymat) --- = 10 Limitations et Améliorations Futures == 10.1 Limitations du Prototype 1. Paramètres ElGamal petits (prototype) - production: 2048+ bits 2. Pas de serveur de mixage - tous les votes par backend 3. Frontend sans chiffrement côté client en JavaScript 4. Pas de blockchain pour immuabilité 5. Pas de biométrie pour authentification == 10.2 Améliorations Futures 1. *Chiffrement Paillier* pour homomorphie plus flexible 2. *Serveurs de mixage* pour anonymat renforcé 3. *Blockchain* pour immuabilité 4. *Authentification biométrique* ou 2FA 5. *Client lourd* chiffrant côté local 6. *Paramètres cryptographiques hardened* --- = 11 Conclusion Ce système démontre comment les concepts cryptographiques fondamentaux (chiffrement asymétrique, preuves ZK, signatures) peuvent être intégrés pour créer un système de vote sécurisé. Les propriétés clés garanties : - ✅ Confidentialité des votes (ElGamal) - ✅ Intégrité (RSA-PSS, SHA-256) - ✅ Auditabilité (journaux, preuves ZK) - ✅ Non-coercibilité (anonymat) Le prototype est fonctionnel, déployable, et extendable. --- = Références - Schneier, B. (2015). "Applied Cryptography: Protocols, Algorithms, and Source Code in C" - ElGamal, T. (1985). "A Public Key Cryptosystem and a Signature Scheme Based on Discrete Logarithms" - Goldwasser, S., & Micali, S. (1984). "Probabilistic encryption & how to play mental poker keeping secret all partial information" - NIST FIPS 186-4: "Digital Signature Standard (DSS)" - RFC 3394: "Advanced Encryption Standard (AES) Key Wrap Algorithm" --- #align(center)[ *Fin du rapport* Version 1.0 - Novembre 2025 ]