Deux approches d'intégrité
Vérifier qu'un fichier n'a pas été modifié peut se faire de deux manières : avec un HMAC (code d'authentification de message basé sur une clé symétrique partagée) ou avec une signature numérique asymétrique (ECDSA). Les deux détectent les modifications, mais avec des propriétés de sécurité très différentes.
La question n'est pas "lequel est plus sécurisé" — les deux offrent une sécurité solide. La question est "qui peut vérifier sans pouvoir générer ?" Si la réponse est "n'importe qui avec la clé publique", il faut ECDSA.
HMAC-SHA256
HMAC utilise une clé symétrique partagée. Quiconque connaît la clé peut à la fois générer et vérifier un HMAC. C'est sa force (simple, rapide) et sa faiblesse (non répudiable).
import hmac, hashlib, os
def generate_hmac(data: bytes, key: bytes) -> bytes:
return hmac.new(key, data, hashlib.sha256).digest()
def verify_hmac(data: bytes, key: bytes, tag: bytes) -> bool:
expected = generate_hmac(data, key)
return hmac.compare_digest(expected, tag)
# Usage : intégrité d'une archive entre deux systèmes qui partagent la clé
key = os.urandom(32)
data = open('archive.uxc', 'rb').read()
tag = generate_hmac(data, key)
# Transmettre tag + data → le destinataire vérifie avec la même clé
ECDSA
ECDSA utilise une paire de clés asymétrique. Seul le détenteur de la clé privée peut générer une signature. N'importe qui avec la clé publique peut vérifier — sans pouvoir forger une nouvelle signature.
from cryptography.hazmat.primitives.asymmetric import ec
from cryptography.hazmat.primitives import hashes
def sign_file(data: bytes, private_key) -> bytes:
return private_key.sign(data, ec.ECDSA(hashes.SHA384()))
def verify_file(data: bytes, sig: bytes, public_key) -> bool:
try:
public_key.verify(sig, data, ec.ECDSA(hashes.SHA384()))
return True
except: return False
# La clé privée reste chez l'éditeur
# La clé publique est distribuée avec le logiciel
# → l'utilisateur ne peut pas forger de signature
Matrice de décision
| Cas d'usage | HMAC | ECDSA |
|---|---|---|
| Intégrité interne (logs, DB, cache) | ✓ Recommandé | Surdimensionné |
| Communication entre 2 services de confiance | ✓ Simple | Possible |
| Signature de licence logicielle | ✗ Client peut forger | ✓ Obligatoire |
| Archive distribuée au public | ✗ Clé à partager | ✓ Recommandé |
| Token d'authentification API | ✓ HMAC-SHA256 (JWT HS256) | Plus lourd (RS256/ES256) |
| Non-répudiation contractuelle | ✗ Impossible | ✓ Seul choix |
| Performance > 1 M ops/sec | ✓ ~10ns/op | ~0.3ms/op |
| Mise à jour OTA signée | ✗ Clé dans le client | ✓ Recommandé |
Implémentation Python — helper unifié
class IntegrityChecker:
def __init__(self, mode: str, key):
# mode = 'hmac' ou 'ecdsa'
self.mode = mode
self.key = key
def sign(self, data: bytes) -> bytes:
if self.mode == 'hmac':
return hmac.new(self.key, data, hashlib.sha256).digest()
return self.key.sign(data, ec.ECDSA(hashes.SHA384()))
def verify(self, data: bytes, tag: bytes) -> bool:
if self.mode == 'hmac':
expected = hmac.new(self.key, data, hashlib.sha256).digest()
return hmac.compare_digest(expected, tag)
try:
self.key.verify(tag, data, ec.ECDSA(hashes.SHA384()))
return True
except: return False
Dans IronLock v2
IronLock v2 utilise les deux mécanismes selon le contexte :
- HMAC-SHA256 sur le header du fichier .ironenc — vérification d'intégrité rapide avant déchiffrement. Clé dérivée du fingerprint hardware (symétrique par nature).
- ECDSA P-384 sur les fichiers de licence .lic — signature par l'éditeur, vérification par le client. La clé privée ne quitte jamais le serveur de l'éditeur.
Conclusion
HMAC pour l'intégrité symétrique entre parties de confiance. ECDSA dès qu'une partie ne doit pas pouvoir générer de signature. La règle est simple : si vous distribuez quelque chose à des clients qui ne doivent pas pouvoir le falsifier, il faut ECDSA. Pour le reste, HMAC suffit et est 30 000× plus rapide.