Restores all missing project files and fixes:
- Restored backend/blockchain.py with full blockchain implementation
- Restored backend/routes/votes.py with all API endpoints
- Restored frontend/components/voting-interface.tsx voting UI
- Fixed backend/crypto/hashing.py to handle both str and bytes
- Fixed pyproject.toml for Poetry compatibility
- All cryptographic modules tested and working
- ElGamal encryption, ZK proofs, digital signatures functional
- Blockchain integrity verification working
- Homomorphic vote counting implemented and tested
Phase 2 Backend API: ✓ COMPLETE
Phase 3 Frontend Interface: ✓ COMPLETE
Verification:
✓ Frontend builds successfully (12 routes)
✓ Backend crypto modules all import correctly
✓ Full voting simulation works end-to-end
✓ Blockchain records and verifies votes
✓ Homomorphic vote counting functional
🤖 Generated with Claude Code
Co-Authored-By: Claude <noreply@anthropic.com>
81 lines
2.2 KiB
Python
81 lines
2.2 KiB
Python
"""
|
|
Fonctions de hachage cryptographique pour intégrité et dérivation de clés.
|
|
"""
|
|
|
|
from cryptography.hazmat.primitives import hashes
|
|
from cryptography.hazmat.backends import default_backend
|
|
from cryptography.hazmat.primitives.kdf.pbkdf2 import PBKDF2HMAC
|
|
from typing import Tuple
|
|
import os
|
|
|
|
|
|
class SecureHash:
|
|
"""
|
|
Hachage cryptographique sécurisé avec SHA-256.
|
|
Utilisé pour:
|
|
- Vérifier l'intégrité des données
|
|
- Dériver des clés
|
|
- Identifier les votes
|
|
"""
|
|
|
|
@staticmethod
|
|
def sha256(data: bytes) -> bytes:
|
|
"""Calculer le hash SHA-256"""
|
|
if isinstance(data, str):
|
|
data = data.encode()
|
|
digest = hashes.Hash(
|
|
hashes.SHA256(),
|
|
backend=default_backend()
|
|
)
|
|
digest.update(data)
|
|
return digest.finalize()
|
|
|
|
@staticmethod
|
|
def sha256_hex(data: bytes) -> str:
|
|
"""SHA-256 en hexadécimal"""
|
|
if isinstance(data, str):
|
|
data = data.encode()
|
|
return SecureHash.sha256(data).hex()
|
|
|
|
@staticmethod
|
|
def derive_key(password: bytes, salt: bytes = None, length: int = 32) -> Tuple[bytes, bytes]:
|
|
"""
|
|
Dériver une clé à partir d'un mot de passe avec PBKDF2.
|
|
|
|
Returns:
|
|
(key, salt) - salt pour stocker et retrouver la clé
|
|
"""
|
|
if salt is None:
|
|
salt = os.urandom(16)
|
|
|
|
kdf = PBKDF2HMAC(
|
|
algorithm=hashes.SHA256(),
|
|
length=length,
|
|
salt=salt,
|
|
iterations=100000,
|
|
backend=default_backend()
|
|
)
|
|
|
|
key = kdf.derive(password)
|
|
return key, salt
|
|
|
|
@staticmethod
|
|
def hash_bulletin(vote_id: int, candidate_id: int, timestamp: int) -> str:
|
|
"""
|
|
Générer un identifiant unique pour un bulletin.
|
|
Utilisé pour l'anonymat + traçabilité.
|
|
"""
|
|
data = f"{vote_id}:{candidate_id}:{timestamp}".encode()
|
|
return SecureHash.sha256_hex(data)
|
|
|
|
@staticmethod
|
|
def hash_vote_commitment(encrypted_vote: bytes, random_salt: bytes) -> str:
|
|
"""
|
|
Hash d'un vote chiffré pour commitments.
|
|
"""
|
|
combined = encrypted_vote + random_salt
|
|
return SecureHash.sha256_hex(combined)
|
|
|
|
|
|
from typing import Tuple
|