Définition
Une signature électronique est un mécanisme cryptographique qui garantit :
- Authenticité : le message provient bien du signataire.
- Intégrité : le message n’a pas été modifié.
- Non-répudiation : le signataire ne peut pas nier avoir signé.
Elle repose sur la cryptographie asymétrique : une clé privée pour signer, une clé publique pour vérifier.
2️⃣ Principe général
Étape 1 – Calcul du haché
On calcule un condensat du message :
H = Hash(message)
Étape 2 – Signature du haché
Le haché est chiffré avec la clé privée du signataire :
S = Chiffrer(H, clé_privée)
Étape 3 – Vérification
- Le destinataire déchiffre
S
avec la clé publique →H'
- Il recalcule le haché du message reçu →
H
- Il compare : si
H' = H
→ la signature est valide ✅
(Message + Signature) → Vérification → Clé publique → OK / NON
3️⃣ Exemple simplifié
Étape | Opération | Résultat |
---|---|---|
1 | Hachage SHA-256 | a3b9…ef2 |
2 | Signature avec clé privée RSA | 0x7c2a…d9e |
3 | Vérification avec clé publique | OK |
La signature ne chiffre pas le message : elle authentifie son auteur et garantit qu’il n’a pas été modifié.
4️⃣ Signature vs chiffrement
Objectif | Clé utilisée | But |
---|---|---|
Chiffrement | Clé publique pour chiffrer, clé privée pour déchiffrer | Confidentialité |
Signature | Clé privée pour signer, clé publique pour vérifier | Authenticité |
5️⃣ Standards et formats
- Algorithmes : RSA, DSA, ECDSA
- Fonctions de hachage : SHA-256, SHA-512
- Certificats : X.509 (clé publique + identité)
- Formats de signature : PKCS#7, PAdES (PDF), XAdES (XML)
6️⃣ Usages concrets
- Signature des e-mails (PGP, S/MIME)
- Signature des logiciels (Microsoft, APK, Linux)
- Signature de documents PDF ou factures électroniques
- Authentification TLS (certificats serveurs HTTPS)
À retenir
- La signature électronique garantit intégrité et authenticité.
- Elle repose sur une clé privée (signature) et une clé publique (vérification).
- Elle est au cœur de la sécurité des échanges numériques.
TD – Pratique avec OpenSSL et Python
Objectif
Signer et vérifier un message avec des outils réels (OpenSSL et Python).
Partie 1 – OpenSSL
# 1. Génération des clés RSA
openssl genrsa -out cle_privee.pem 2048
openssl rsa -in cle_privee.pem -pubout -out cle_publique.pem
# 2. Fichier à signer
echo "Message confidentiel" > message.txt
# 3. Signature
openssl dgst -sha256 -sign cle_privee.pem -out signature.bin message.txt
# 4. Vérification
openssl dgst -sha256 -verify cle_publique.pem -signature signature.bin message.txt
# => Verified OK
Exercice : modifier le contenu du fichier message.txt
puis relancer la vérification. Que se passe-t-il ? Pourquoi ?
Partie 2 – Python (bibliothèque cryptography)
from cryptography.hazmat.primitives import hashes, serialization
from cryptography.hazmat.primitives.asymmetric import padding, rsa
# Génération de la paire de clés
private_key = rsa.generate_private_key(public_exponent=65537, key_size=2048)
public_key = private_key.public_key()
message = b"Signature test BTS SIO SLAM"
# Signature du message
signature = private_key.sign(
message,
padding.PKCS1v15(),
hashes.SHA256()
)
# Vérification
try:
public_key.verify(
signature,
message,
padding.PKCS1v15(),
hashes.SHA256()
)
print("Signature valide")
except Exception:
print("Signature invalide")
Question : que se passe-t-il si vous changez une lettre dans message
avant la vérification ?
Outils utilisés : OpenSSL (terminal) et Python cryptography
pour visualiser le lien entre théorie et pratique.
Explication : génération et rôle des clés RSA
private_key = rsa.generate_private_key(public_exponent=65537, key_size=2048)
public_key = private_key.public_key()
1) Génération de la clé privée
La fonction rsa.generate_private_key()
crée une paire de clés RSA :
- une clé privée, stockée dans
private_key
; - et implicitement une clé publique, dérivée de la clé privée.
Les deux paramètres sont importants :
public_exponent=65537
→ valeur standard sûre utilisée dans presque tous les systèmes RSA modernes ;key_size=2048
→ taille de clé en bits : 2048 bits est le minimum recommandé pour une bonne sécurité.
Concrètement, Python génère deux grands nombres premiers aléatoires p
et q
, calcule n = p × q
, puis détermine l’exposant public e
(ici 65537) et la clé privée d
telle que e × d ≡ 1 (mod φ(n))
.
2) Extraction de la clé publique
La ligne suivante :
public_key = private_key.public_key()
extrait la clé publique correspondant à la clé privée.
On peut donc dériver la clé publique à partir de la clé privée, mais jamais l’inverse.
Clé | Utilisation | Confidentialité |
---|---|---|
private_key |
Signer ou déchiffrer | Doit rester secrète |
public_key |
Vérifier ou chiffrer | Peut être diffusée |
rsa.generate_private_key(…) ───► private_key
│
▼
public_key = private_key.public_key()
- La clé privée signe ou déchiffre les messages.
- La clé publique vérifie ou chiffre les messages.
- Ensemble, elles assurent authenticité, intégrité et confidentialité.
Stockage et réutilisation des clés RSA
Lorsqu’on exécute le code :
private_key = rsa.generate_private_key(public_exponent=65537, key_size=2048)
public_key = private_key.public_key()
les clés existent uniquement en mémoire.
Si vous fermez le programme, elles sont perdues.
Il faut donc les enregistrer dans des fichiers au format PEM pour pouvoir les réutiliser.
🔹 Sauvegarder la clé privée
from cryptography.hazmat.primitives import serialization
with open("cle_privee.pem", "wb") as f:
f.write(
private_key.private_bytes(
encoding=serialization.Encoding.PEM,
format=serialization.PrivateFormat.TraditionalOpenSSL,
encryption_algorithm=serialization.NoEncryption() # Pour TP uniquement
)
)
Ce fichier cle_privee.pem
contient la clé privée RSA.
Ne le partagez jamais : il doit rester strictement confidentiel (comme un mot de passe).
Sauvegarder la clé publique
with open("cle_publique.pem", "wb") as f:
f.write(
public_key.public_bytes(
encoding=serialization.Encoding.PEM,
format=serialization.PublicFormat.SubjectPublicKeyInfo
)
)
Le fichier cle_publique.pem
contient la clé publique correspondante.
Vous pouvez le diffuser librement : il servira à vérifier vos signatures.
Structure conseillée
signature_elec/ │ ├── cle_privee.pem ← confidentielle ├── cle_publique.pem ← partageable ├── message.txt ├── signature.bin └── signer.py / verifier.py
Charger les clés existantes
Pour réutiliser les clés sauvegardées :
# Charger la clé privée
with open("cle_privee.pem", "rb") as f:
private_key = serialization.load_pem_private_key(f.read(), password=None)
# Charger la clé publique
with open("cle_publique.pem", "rb") as f:
public_key = serialization.load_pem_public_key(f.read())
- Clé privée → pour signer ou déchiffrer.
- Clé publique → pour vérifier ou chiffrer.
- En production, les clés doivent être protégées par mot de passe ou stockées dans un HSM.
Exemple complet
from cryptography.hazmat.primitives import hashes, serialization
from cryptography.hazmat.primitives.asymmetric import padding, rsa
# Génération
private_key = rsa.generate_private_key(public_exponent=65537, key_size=2048)
public_key = private_key.public_key()
# Sauvegarde
with open("cle_privee.pem", "wb") as f:
f.write(private_key.private_bytes(
encoding=serialization.Encoding.PEM,
format=serialization.PrivateFormat.TraditionalOpenSSL,
encryption_algorithm=serialization.NoEncryption()
))
with open("cle_publique.pem", "wb") as f:
f.write(public_key.public_bytes(
encoding=serialization.Encoding.PEM,
format=serialization.PublicFormat.SubjectPublicKeyInfo
))
print("Clés générées et sauvegardées.")
Ce contenu est réservé aux membres du site. Si vous êtes un utilisateur existant, veuillez vous connecter. Les nouveaux utilisateurs peuvent s'inscrire ci-dessous.