Plateforme de Cryptographie Par Kaci AMAOUCHE

Exercices - Cryptosystèmes avancés

Applications pratiques des systèmes RSA, DH et ECC


Exercice 1: Génération et analyse de clés RSA

Objectifs
  • Générer des clés RSA de différentes tailles
  • Analyser leurs structures et propriétés
  • Évaluer l'impact de la taille des clés sur les performances

Partie 1: Génération de clés RSA

Utilisez OpenSSL pour générer des clés RSA de 1024, 2048, 3072 et 4096 bits :

openssl genrsa -out rsa_1024.pem 1024
openssl genrsa -out rsa_2048.pem 2048
openssl genrsa -out rsa_3072.pem 3072
openssl genrsa -out rsa_4096.pem 4096

Examinez chaque clé avec la commande :

openssl rsa -in rsa_2048.pem -text -noout

Partie 2: Questions d'analyse

  1. Identifiez dans l'output de la commande openssl rsa -text les valeurs de n, e, d, p et q. Vérifiez que n = p × q.
  2. Qu'est-ce que les valeurs exponent1, exponent2 et coefficient représentent dans la sortie ? Pourquoi sont-elles stockées ?
  3. Mesurez le temps nécessaire pour générer chacune des clés. Comment évolue ce temps en fonction de la taille des clés ?

Partie 3: Benchmark de performances

Évaluez l'impact de la taille des clés sur les performances de chiffrement et de déchiffrement :

# Créez un fichier de test
dd if=/dev/urandom of=testfile bs=1M count=1

# Mesurez le temps pour les opérations avec différentes tailles de clés
time openssl pkeyutl -encrypt -in testfile -inkey rsa_1024.pem -out enc_1024
time openssl pkeyutl -decrypt -in enc_1024 -inkey rsa_1024.pem -out dec_1024

# Répétez avec les autres tailles de clés

Question : Analysez les résultats et expliquez pourquoi RSA est généralement utilisé pour chiffrer de petites quantités de données (comme des clés symétriques) plutôt que des fichiers entiers.

Exercice 2: Implémentation de RSA-OAEP

Objectifs
  • Comprendre le schéma de rembourrage OAEP (Optimal Asymmetric Encryption Padding)
  • Implémenter le chiffrement et déchiffrement RSA avec OAEP
  • Comparer avec RSA "brut" pour identifier les avantages de sécurité

Partie 1: Utilisation de RSA-OAEP avec OpenSSL

Générez une paire de clés RSA et utilisez le schéma OAEP pour chiffrer un message :

# Générer une clé RSA de 2048 bits
openssl genrsa -out private_key.pem 2048

# Extraire la clé publique
openssl rsa -in private_key.pem -pubout -out public_key.pem

# Créer un message test
echo "Message secret à chiffrer avec RSA-OAEP" > message.txt

# Chiffrer avec RSA-OAEP (utilisant SHA-256)
openssl pkeyutl -encrypt -in message.txt -out message.enc \
  -inkey public_key.pem -pubin \
  -pkeyopt rsa_padding_mode:oaep \
  -pkeyopt rsa_oaep_md:sha256

# Déchiffrer avec RSA-OAEP
openssl pkeyutl -decrypt -in message.enc -out message.dec \
  -inkey private_key.pem \
  -pkeyopt rsa_padding_mode:oaep \
  -pkeyopt rsa_oaep_md:sha256

Partie 2: Comparaison avec RSA PKCS#1 v1.5

Répétez l'exercice en utilisant le rembourrage PKCS#1 v1.5 :

# Chiffrer avec PKCS#1 v1.5
openssl pkeyutl -encrypt -in message.txt -out message_pkcs1.enc \
  -inkey public_key.pem -pubin \
  -pkeyopt rsa_padding_mode:pkcs1

# Déchiffrer avec PKCS#1 v1.5
openssl pkeyutl -decrypt -in message_pkcs1.enc -out message_pkcs1.dec \
  -inkey private_key.pem \
  -pkeyopt rsa_padding_mode:pkcs1

Partie 3: Questions d'analyse

  1. Observez et comparez les tailles des fichiers chiffrés avec les deux méthodes. Pourquoi diffèrent-elles ?
  2. Recherchez et expliquez l'attaque de Bleichenbacher contre PKCS#1 v1.5. Pourquoi OAEP est-il considéré comme plus sûr ?
  3. Essayez de chiffrer un fichier plus grand que la taille maximale autorisée (environ 190 octets pour RSA-2048 avec OAEP-SHA256). Que se passe-t-il et comment contourner cette limitation dans une application réelle ?

Exercice 3: Mise en œuvre de l'échange de clés Diffie-Hellman

Objectifs
  • Comprendre et implémenter l'échange de clés Diffie-Hellman
  • Générer et utiliser des paramètres DH
  • Établir une clé partagée entre deux parties

Partie 1: Génération des paramètres DH

Générez un ensemble de paramètres Diffie-Hellman (p, g) :

# Générer des paramètres DH (2048 bits)
openssl dhparam -out dhparams.pem 2048

# Examiner les paramètres
openssl dhparam -in dhparams.pem -text -noout

Partie 2: Simulation d'un échange DH

Nous allons simuler l'échange de clés entre Alice et Bob :

# Alice génère sa clé privée et sa clé publique
openssl genpkey -paramfile dhparams.pem -out alice_private.pem
openssl pkey -in alice_private.pem -pubout -out alice_public.pem

# Bob génère sa clé privée et sa clé publique
openssl genpkey -paramfile dhparams.pem -out bob_private.pem
openssl pkey -in bob_private.pem -pubout -out bob_public.pem

# Alice calcule la clé partagée en utilisant sa clé privée et la clé publique de Bob
openssl pkeyutl -derive -inkey alice_private.pem -peerkey bob_public.pem -out alice_shared_secret.bin

# Bob calcule la clé partagée en utilisant sa clé privée et la clé publique d'Alice
openssl pkeyutl -derive -inkey bob_private.pem -peerkey alice_public.pem -out bob_shared_secret.bin

# Vérifier que les secrets partagés sont identiques
cmp alice_shared_secret.bin bob_shared_secret.bin
# Afficher un hachage des secrets pour confirmer visuellement
sha256sum alice_shared_secret.bin bob_shared_secret.bin

Partie 3: Application pratique

Utilisez la clé partagée pour chiffrer un message avec AES-256-CBC :

# Créer un IV (vecteur d'initialisation) aléatoire
openssl rand -out iv.bin 16

# Créer une clé de chiffrement à partir du secret partagé (en prenant les 32 premiers octets)
head -c 32 alice_shared_secret.bin > aes_key.bin

# Alice chiffre un message
echo "Message secret chiffré avec une clé dérivée de DH" > message.txt
openssl enc -aes-256-cbc -in message.txt -out message.enc -K $(xxd -p -c 32 aes_key.bin) -iv $(xxd -p -c 16 iv.bin)

# Bob déchiffre le message
openssl enc -d -aes-256-cbc -in message.enc -out message.dec -K $(xxd -p -c 32 aes_key.bin) -iv $(xxd -p -c 16 iv.bin)

# Vérifier que le message déchiffré correspond à l'original
cat message.dec

Partie 4: Questions d'analyse

  1. Pourquoi l'échange DH fournit-il une clé partagée sécurisée même sur un canal non sécurisé où un attaquant peut voir toutes les communications ?
  2. Que se passerait-il si un attaquant pouvait modifier les messages échangés (attaque de l'homme du milieu) ? Comment pourrait-on protéger l'échange DH contre cette attaque ?
  3. Dans l'exemple ci-dessus, nous avons utilisé directement la clé partagée pour le chiffrement AES. Dans la pratique, pourquoi est-il préférable d'utiliser une fonction de dérivation de clé (KDF) sur le secret partagé ?

Exercice 4: Exploration de la cryptographie sur courbes elliptiques

Objectifs
  • Générer et manipuler des clés basées sur les courbes elliptiques
  • Utiliser ECDH (Elliptic Curve Diffie-Hellman) pour établir une clé partagée
  • Comparer les performances et la taille des clés entre ECC et RSA

Partie 1: Exploration des courbes disponibles

Commencez par explorer les courbes elliptiques disponibles dans OpenSSL :

# Liste des courbes elliptiques supportées
openssl ecparam -list_curves

Partie 2: Génération et analyse de clés EC

Générez des clés pour différentes courbes elliptiques :

# Générer des paramètres et des clés pour secp256r1 (P-256)
openssl ecparam -name prime256v1 -out ec_p256.pem
openssl ecparam -in ec_p256.pem -genkey -noout -out ec_p256_key.pem
openssl ec -in ec_p256_key.pem -text -noout

# Générer des paramètres et des clés pour secp384r1 (P-384)
openssl ecparam -name secp384r1 -out ec_p384.pem
openssl ecparam -in ec_p384.pem -genkey -noout -out ec_p384_key.pem
openssl ec -in ec_p384_key.pem -text -noout

Partie 3: Mise en œuvre d'ECDH

Implémentez un échange de clés ECDH entre Alice et Bob :

# Alice génère sa paire de clés
openssl ecparam -name prime256v1 -genkey -noout -out alice_ec_key.pem
openssl ec -in alice_ec_key.pem -pubout -out alice_ec_pub.pem

# Bob génère sa paire de clés
openssl ecparam -name prime256v1 -genkey -noout -out bob_ec_key.pem
openssl ec -in bob_ec_key.pem -pubout -out bob_ec_pub.pem

# Alice calcule la clé partagée
openssl pkeyutl -derive -inkey alice_ec_key.pem -peerkey bob_ec_pub.pem -out alice_ec_shared.bin

# Bob calcule la clé partagée
openssl pkeyutl -derive -inkey bob_ec_key.pem -peerkey alice_ec_pub.pem -out bob_ec_shared.bin

# Vérifier que les clés partagées sont identiques
cmp alice_ec_shared.bin bob_ec_shared.bin
sha256sum alice_ec_shared.bin bob_ec_shared.bin

Partie 4: Comparaison avec RSA

Comparez les performances et les tailles des clés entre ECC et RSA :

# Générer une clé RSA de 2048 bits (niveau de sécurité ~112 bits)
openssl genrsa -out rsa_2048.pem 2048

# Mesurer le temps pour différentes opérations
time openssl speed rsa2048
time openssl speed ecdhp256

# Comparer les tailles des clés
ls -l *_key.pem

Partie 5: Questions d'analyse

  1. Comparez la taille des fichiers contenant les clés privées RSA et ECC. Quelle est la différence approximative ?
  2. Sur la base des résultats du benchmark, comparez les performances des opérations cryptographiques entre RSA et ECC. Quels avantages voyez-vous pour chaque approche ?
  3. Identifiez au moins trois applications ou protocoles qui utilisent les courbes elliptiques et expliquez pourquoi ECC a été choisi plutôt que RSA dans ces cas.

Exercice 5: Attaques et limitations des cryptosystèmes

Objectifs
  • Comprendre les vulnérabilités potentielles des cryptosystèmes
  • Simuler et analyser des attaques simplifiées
  • Développer des bonnes pratiques pour l'implémentation sécurisée

Partie 1: Attaque par exposant faible sur RSA

Simulez une attaque sur RSA lorsqu'un petit exposant public est utilisé sans rembourrage approprié :

# Générer une clé RSA avec un exposant e=3 (normalement déconseillé)
openssl genrsa -3 -out rsa_weak_exp.pem 1024

# Extraire la clé publique et l'examiner pour vérifier l'exposant
openssl rsa -in rsa_weak_exp.pem -pubout -out rsa_weak_exp_pub.pem
openssl rsa -pubin -in rsa_weak_exp_pub.pem -text -noout

Pour cet exercice, nous allons utiliser Python pour simuler l'attaque. Créez un script rsa_cube_root_attack.py :

#!/usr/bin/env python3
import math
from cryptography.hazmat.primitives.asymmetric import rsa
from cryptography.hazmat.primitives.serialization import load_pem_public_key

# Charger la clé publique
with open('rsa_weak_exp_pub.pem', 'rb') as f:
    public_key = load_pem_public_key(f.read())

# Récupérer le module n et l'exposant e
n = public_key.public_numbers().n
e = public_key.public_numbers().e

print(f"Module n: {n}")
print(f"Exposant e: {e}")

# Message à chiffrer (un petit nombre pour faciliter l'attaque)
m = 42
print(f"Message original: {m}")

# Chiffrement RSA direct (sans rembourrage)
c = pow(m, e, n)
print(f"Message chiffré: {c}")

# Attaque par racine cubique (si e=3)
if e == 3:
    # Calcul de la racine cubique de c
    m_recovered = round(c ** (1/3))
    print(f"Message récupéré par attaque de racine cubique: {m_recovered}")

    # Vérification
    if pow(m_recovered, e, n) == c:
        print("Attaque réussie!")
    else:
        print("Attaque échouée.")
else:
    print(f"Cette attaque ne fonctionne que pour e=3 (actuel: {e})")

Exécutez le script et analysez les résultats :

python3 rsa_cube_root_attack.py

Partie 2: Démonstration de l'attaque de l'homme du milieu

Simulez une attaque de l'homme du milieu sur l'échange Diffie-Hellman :

# Script simulant une attaque MITM sur DH
cat > dh_mitm.sh << 'EOF'
#!/bin/bash
echo "=== Simulation d'une attaque de l'homme du milieu sur Diffie-Hellman ==="

# Générer les paramètres DH
openssl dhparam -out dhparams.pem 2048
echo "Paramètres DH générés"

# Alice génère sa paire de clés
openssl genpkey -paramfile dhparams.pem -out alice_private.pem
openssl pkey -in alice_private.pem -pubout -out alice_public.pem
echo "Alice a généré sa paire de clés"

# Bob génère sa paire de clés
openssl genpkey -paramfile dhparams.pem -out bob_private.pem
openssl pkey -in bob_private.pem -pubout -out bob_public.pem
echo "Bob a généré sa paire de clés"

# Mallory (l'attaquant) génère sa propre paire de clés
openssl genpkey -paramfile dhparams.pem -out mallory_private.pem
openssl pkey -in mallory_private.pem -pubout -out mallory_public.pem
echo "Mallory (attaquant) a généré sa paire de clés"

echo -e "\n=== COMMUNICATION NORMALE (sans attaque) ==="
# Alice et Bob calculent leur clé partagée
openssl pkeyutl -derive -inkey alice_private.pem -peerkey bob_public.pem -out alice_shared_key.bin
openssl pkeyutl -derive -inkey bob_private.pem -peerkey alice_public.pem -out bob_shared_key.bin

# Vérifier que les clés sont identiques
echo "Clés partagées en hexadécimal :"
xxd -p alice_shared_key.bin | head -c 32
echo
xxd -p bob_shared_key.bin | head -c 32
echo

cmp alice_shared_key.bin bob_shared_key.bin &> /dev/null
if [ $? -eq 0 ]; then
    echo "Communication sécurisée: Alice et Bob ont la même clé partagée"
else
    echo "ERREUR: Les clés partagées diffèrent"
fi

echo -e "\n=== AVEC ATTAQUE DE L'HOMME DU MILIEU ==="
# Mallory intercepte les clés publiques et les remplace par la sienne
echo "Mallory intercepte les communications et substitue sa propre clé publique"

# Alice calcule une clé partagée avec Mallory (croyant communiquer avec Bob)
openssl pkeyutl -derive -inkey alice_private.pem -peerkey mallory_public.pem -out alice_compromised_key.bin
echo "Alice a calculé une clé partagée (avec Mallory)"

# Bob calcule une clé partagée avec Mallory (croyant communiquer avec Alice)
openssl pkeyutl -derive -inkey bob_private.pem -peerkey mallory_public.pem -out bob_compromised_key.bin
echo "Bob a calculé une clé partagée (avec Mallory)"

# Mallory calcule des clés partagées avec Alice et Bob
openssl pkeyutl -derive -inkey mallory_private.pem -peerkey alice_public.pem -out mallory_alice_key.bin
openssl pkeyutl -derive -inkey mallory_private.pem -peerkey bob_public.pem -out mallory_bob_key.bin
echo "Mallory a calculé des clés partagées avec Alice et Bob"

# Vérifier l'attaque
echo "Clés compromises en hexadécimal :"
echo "Alice-Mallory: $(xxd -p alice_compromised_key.bin | head -c 32)"
echo "Mallory-Alice: $(xxd -p mallory_alice_key.bin | head -c 32)"
echo "Bob-Mallory:   $(xxd -p bob_compromised_key.bin | head -c 32)"
echo "Mallory-Bob:   $(xxd -p mallory_bob_key.bin | head -c 32)"

# Vérifier que Mallory peut décoder les communications
cmp alice_compromised_key.bin mallory_alice_key.bin &> /dev/null
cmp bob_compromised_key.bin mallory_bob_key.bin &> /dev/null
if [ $? -eq 0 ]; then
    echo "ATTAQUE RÉUSSIE: Mallory peut intercepter et décoder toutes les communications"
    echo "Alice et Bob ont des clés différentes et ne peuvent pas communiquer directement"
    cmp alice_compromised_key.bin bob_compromised_key.bin &> /dev/null
    if [ $? -ne 0 ]; then
        echo "Confirmation: La clé d'Alice ($(xxd -p alice_compromised_key.bin | head -c 8)...) ≠ La clé de Bob ($(xxd -p bob_compromised_key.bin | head -c 8)...)"
    fi
else
    echo "L'attaque a échoué"
fi

echo -e "\n=== SOLUTION: Authentification des clés publiques ==="
echo "Pour prévenir cette attaque, les clés publiques doivent être authentifiées, par exemple via:"
echo "- Signatures numériques (protocole 'Station-to-Station')"
echo "- Certificats numériques (infrastructure à clé publique)"
echo "- Vérification hors bande (comparaison manuelle d'empreintes)"
EOF

chmod +x dh_mitm.sh
./dh_mitm.sh

Partie 3: Questions d'analyse

  1. Dans l'attaque par exposant faible, pourquoi un message court peut-il être récupéré alors qu'un message long ne le pourrait pas ? Comment le rembourrage protège-t-il contre cette attaque ?
  2. Dans l'attaque de l'homme du milieu, comment Mallory parvient-elle à compromettre l'échange de clés sans que Alice et Bob ne s'en aperçoivent ? Comment une authentification mutuelle résolverait-elle ce problème ?
  3. Décrivez deux autres attaques potentielles contre les cryptosystèmes étudiés dans ce chapitre et leurs contre-mesures respectives.

Ressources pour les exercices

Outils nécessaires
  • OpenSSL (version 1.1.1 ou supérieure)
  • Python 3 avec les packages cryptography et gmpy2
  • Bash ou tout autre interpréteur de commandes Unix
Documentation utile

Conseils pour les exercices

  • Si vous rencontrez des problèmes avec OpenSSL, consultez les messages d'erreur détaillés avec l'option -text.
  • Pour les exercices d'attaque, travaillez avec des valeurs petites et contrôlées pour mieux comprendre les concepts.
  • N'hésitez pas à consulter les RFC et standards correspondants pour des détails supplémentaires sur les algorithmes.
  • Utilisez des fonctions de hachage cryptographiques pour vérifier l'intégrité des données entre les différentes étapes des exercices.