Documentation & Explications du projet de cryptographie post-quantique hybride
Ce projet met en œuvre un protocole d'échange de clés hybride combinant RSA (cryptographie classique) et Kyber (cryptographie post-quantique) pour sécuriser les communications entre deux parties, Alice et Bob.
[À compléter : Décrivez chaque étape, les fichiers échangés, la synchronisation, etc.]
La sécurité du protocole repose sur la génération de paires de clés robustes pour chaque participant (Alice et Bob), à la fois pour l'algorithme classique RSA et pour l'algorithme post-quantique Kyber.
# Génération d'une paire de clés RSA pour Bob
from cryptography.hazmat.primitives.asymmetric import rsa
from cryptography.hazmat.primitives import serialization
rsa_private = rsa.generate_private_key(public_exponent=65537, key_size=2048)
# Sauvegarde de la clé privée
with open("bob_rsa_private.pem", "wb") as f:
f.write(rsa_private.private_bytes(
encoding=serialization.Encoding.PEM,
format=serialization.PrivateFormat.PKCS8,
encryption_algorithm=serialization.NoEncryption()
))
# Export de la clé publique dans le dossier d'Alice
with open(r"C:\Users\zoran\Documents\Projet_Crypto\Alice\bob_rsa_public.pem", "wb") as f:
f.write(rsa_private.public_key().public_bytes(
encoding=serialization.Encoding.PEM,
format=serialization.PublicFormat.SubjectPublicKeyInfo
))
# Génération d'une paire de clés Kyber pour Bob
import simple_kyber512
pk, sk = simple_kyber512.keygen()
# Sauvegarde des clés
with open("bob_kyber_pk.bin", "wb") as f:
f.write(pk)
with open("bob_kyber_sk.bin", "wb") as f:
f.write(sk)
# Export de la clé publique dans le dossier d'Alice
import os
alice_dir = r"C:\Users\zoran\Documents\Projet_Crypto\Alice"
os.makedirs(alice_dir, exist_ok=True)
with open(os.path.join(alice_dir, "bob_kyber_pk.bin"), "wb") as f:
f.write(pk)
Résumé : Chaque participant dispose ainsi de ses propres clés privées (RSA et Kyber) et exporte ses clés publiques dans le dossier de l'autre, permettant à chacun de chiffrer des secrets à destination de l'autre.
L'encapsulation permet à une partie (ex : Bob) de générer un secret partagé, de le chiffrer avec la clé publique de l'autre (ex : Alice), puis de lui transmettre ce secret chiffré. La décapsulation permet à Alice de retrouver ce secret à l'aide de sa clé privée. Ce mécanisme est réalisé à la fois pour RSA (classique) et Kyber (post-quantique).
# Encapsulation RSA (Bob)
from cryptography.hazmat.primitives.asymmetric import padding
from cryptography.hazmat.primitives import hashes
import os
K_RSA_to_alice = os.urandom(32) # Génère un secret aléatoire
C_RSA_to_alice = alice_rsa_public.encrypt(
K_RSA_to_alice,
padding.OAEP(
mgf=padding.MGF1(algorithm=hashes.SHA256()),
algorithm=hashes.SHA256(),
label=None
)
)
# Bob envoie C_RSA_to_alice à Alice
# Décapsulation RSA (Alice)
K_RSA_from_bob = alice_rsa_private.decrypt(
C_RSA_to_alice,
padding.OAEP(
mgf=padding.MGF1(algorithm=hashes.SHA256()),
algorithm=hashes.SHA256(),
label=None
)
)
# Alice retrouve le même secret K_RSA_to_alice
Avantage : RSA est bien connu et robuste contre les attaques classiques, mais vulnérable à un attaquant quantique. D'où l'intérêt de l'associer à Kyber.
# Encapsulation Kyber (Bob)
import simple_kyber512
C_Kyber_to_alice, K_Kyber_to_alice = simple_kyber512.encapsulate(alice_kyber_pk)
# Bob envoie C_Kyber_to_alice à Alice
# Décapsulation Kyber (Alice)
K_Kyber_from_bob = simple_kyber512.decapsulate(C_Kyber_to_alice, alice_kyber_sk)
# Alice retrouve le même secret K_Kyber_to_alice
Avantage : Kyber repose sur des problèmes difficiles même pour un ordinateur quantique (lattices), ce qui garantit la sécurité post-quantique du protocole.
Résumé : Les deux encapsulations sont réalisées dans les deux sens (Alice→Bob et Bob→Alice), puis les secrets obtenus sont combinés via HKDF pour obtenir une clé finale commune.
Après l'encapsulation et la décapsulation des secrets RSA et Kyber dans les deux sens (Alice→Bob et Bob→Alice), chaque partie possède quatre secrets :
Pour obtenir une clé de session commune, ces quatre secrets sont concaténés dans le même ordre par Alice et Bob, puis passés à une fonction de dérivation de clé (HKDF avec SHA-256). Cela garantit que la clé finale (K_final) est identique pour les deux parties, tout en étant robuste contre les attaques classiques et quantiques.
# Dérivation de la clé finale commune avec HKDF (extrait des scripts Alice/Bob)
from cryptography.hazmat.primitives.kdf.hkdf import HKDF
from cryptography.hazmat.primitives import hashes
KDF = HKDF(
algorithm=hashes.SHA256(),
length=32,
salt=None,
info=b"KEM_RSA+Kyber",
)
K_final = KDF.derive(
K_RSA_to_alice + K_Kyber_to_alice + K_RSA_to_bob + K_Kyber_to_bob
)
# K_final est la clé symétrique commune utilisée pour AES-GCM
Points importants :
Utilisation : Cette clé K_final sert ensuite à chiffrer/déchiffrer les messages échangés entre Alice et Bob via AES-GCM, assurant la confidentialité et l'intégrité des communications.
Une fois la clé finale K_final dérivée, Alice et Bob peuvent échanger des messages chiffrés en toute sécurité. Le chiffrement symétrique utilisé ici est AES-GCM (Galois/Counter Mode), qui offre à la fois la confidentialité et l'intégrité des messages.
# Chiffrement d'un message (extrait des interfaces Alice/Bob)
from cryptography.hazmat.primitives.ciphers.aead import AESGCM
import os
aesgcm = AESGCM(K_final)
nonce = os.urandom(12)
ciphertext = aesgcm.encrypt(nonce, b"Message secret", None)
# Envoi : écrire nonce + ciphertext dans un fichier partagé
# Déchiffrement d'un message reçu
aesgcm = AESGCM(K_final)
# Lire nonce (12 octets) et ciphertext depuis le fichier
plaintext = aesgcm.decrypt(nonce, ciphertext, None)
# plaintext contient le message original
Avantages d'AES-GCM :
Dans le projet : Les messages sont échangés via des fichiers (ex : message_aesgcm_from_alice.bin
), chaque fichier contenant d'abord le nonce puis le ciphertext. Les interfaces graphiques Alice/Bob automatisent ce processus pour l'utilisateur.
Ce rapport détaille mathématiquement et numériquement le protocole d'échange de clé hybride RSA + Kyber, avec exemples chiffrés, calculs étape par étape, et explications pédagogiques. Les deux parties (Alice et Bob) peuvent initier la procédure, qui est totalement symétrique.
Dans ce protocole hybride, l'encapsulation KEM est réalisée à la fois avec Kyber et avec RSA. Cela signifie que, tout comme pour Kyber, une clé symétrique aléatoire est générée puis encapsulée (chiffrée) à l'aide de la clé publique RSA du destinataire. Cette encapsulation RSA consiste à chiffrer la clé symétrique \( K_{RSA} \) avec la clé publique \((e, n)\) :
Le destinataire décapsule (décrypte) la clé symétrique à l'aide de sa clé privée \( d \) :
Ainsi, le protocole utilise deux KEM indépendants :
Les deux clés symétriques issues de ces encapsulations sont ensuite fusionnées via la KDF pour obtenir la clé finale \( K_{\text{final}} \).
Génération de clés RSA :
Clés générées :
Dans le protocole hybride, l'encapsulation KEM sur RSA consiste à générer une clé symétrique aléatoire \( K_{RSA} \) (par exemple, un entier ou une suite d'octets), puis à la chiffrer avec la clé publique RSA du destinataire.
Paramètres simplifiés :
Génération de la clé publique d'Alice :
Encapsulation par Bob :
Décapsulation par Alice :
decode()
, ici c’est illustratif.)
Concaténation des clés pour la KDF :
73a14453b96e54a32fbc4a8d67870e62ba43a935a79bf269861179b2fc695028
2f0fd1e89b8de1d57292742ec380ea47066e307ad645f5bc3adad8a06ff58608
82de42be5d948f40870bc81fadf1959a8c28e140d88d00f7a2442c133b2cca34
fcb5f40df9be6bae66c1d77a6c15968866a9e6cbd7314ca432b019d17392f6f4
On concatène les clés dans l'ordre suivant (en notation hexadécimale) :
concat = ( bytes.fromhex("73a14453b96e54a32fbc4a8d67870e62ba43a935a79bf269861179b2fc695028") + bytes.fromhex("2f0fd1e89b8de1d57292742ec380ea47066e307ad645f5bc3adad8a06ff58608") + bytes.fromhex("82de42be5d948f40870bc81fadf1959a8c28e140d88d00f7a2442c133b2cca34") + bytes.fromhex("fcb5f40df9be6bae66c1d77a6c15968866a9e6cbd7314ca432b019d17392f6f4") )
Calcul de la KDF (HKDF-SHA256) :
Valeur obtenue dans la démo :
K_final : b759b7c6a96735788d9c1426448cedf653063ca530dcce6f9f3eae04aa1392ea
Supposons que l'on souhaite chiffrer le message "Bonjour Bob"
avec un nonce d'exemple :
00112233445566778899aabb
(12 octets)"Bonjour Bob"
from cryptography.hazmat.primitives.ciphers.aead import AESGCM key = bytes.fromhex("b759b7c6a96735788d9c1426448cedf653063ca530dcce6f9f3eae04aa1392ea") nonce = bytes.fromhex("00112233445566778899aabb") message = b"Bonjour Bob" aesgcm = AESGCM(key) ciphertext = aesgcm.encrypt(nonce, message, None) print(ciphertext.hex())
Remarque : Le résultat du chiffrement dépendra du message, du nonce et de la clé.
Ce protocole hybride RSA + Kyber permet un échange de clé sécurisé, résistant aux attaques classiques et quantiques. Il est totalement symétrique : Alice ou Bob peut initier l’échange. Tous les calculs sont reproductibles et vérifiables étape par étape.
KEM_RSA_Alice.py
file_exists_anywhere(filename, dir1, dir2)
: Vérifie si un fichier nommé filename
existe dans l'un des deux dossiers dir1
ou dir2
. Retourne un booléen.read_anywhere(filename, prefer_dir, other_dir)
: Ouvre et lit le fichier filename
en cherchant d'abord dans prefer_dir
, puis dans other_dir
. Retourne le contenu binaire du fichier.export_keys_if_needed()
: Exporte la clé publique RSA et la clé publique Kyber d'Alice dans le dossier de Bob, pour permettre à Bob de les utiliser pour l'encapsulation.simple_kyber512.py
(version pédagogique)keygen()
: Génère une paire de clés Kyber (publique et privée). En version simplifiée, cela peut être des vecteurs/matrices aléatoires et du bruit.encapsulate(pk)
: Prend une clé publique Kyber, génère un vecteur aléatoire, encapsule une clé symétrique, et retourne l'encapsulation (ciphertext) et la clé partagée.decapsulate(ciphertext, sk)
: Prend l'encapsulation et la clé privée, effectue les opérations inverses pour retrouver la clé partagée.message_aesgcm_from_alice.bin
, message_aesgcm_from_bob.bin
).alice_rsa_public.pem
, bob_kyber_pk.bin
, etc.)C_RSA_to_bob.bin
, K_Kyber_to_alice.bin
, etc.)K_final.bin
message_aesgcm_from_alice.bin
, message_aesgcm_from_bob.bin
)Le code permet un échange de clé hybride sécurisé, automatisé et reproductible, avec gestion complète des fichiers d'échange et possibilité de suppression pour garantir la fraîcheur et la sécurité des échanges.