Le chiffrement RSA fête ses 48 ans en 2026, et il tourne toujours derrière une bonne partie du trafic sécurisé mondial, des certificats de messagerie aux échanges bancaires. Sauf qu’il ne travaille plus seul depuis longtemps. En pratique, personne ne chiffre un fichier de 500 Mo directement avec RSA : trop lent, trop limité en taille. La technique standard s’appelle le chiffrement hybride, RSA pour transporter une clé, AES pour transporter les données. Ce tutoriel montre comment le construire de A à Z, en Python et en ligne de commande OpenSSL, avec des tailles de clés conformes aux recommandations 2026 de l’ANSSI et du NIST.
Douze étapes vérifiées, cinq blocs de code testés sur une machine réelle, un script complet livré en fin d’article. Comptez environ 45 minutes si vous suivez les commandes dans l’ordre.
Ce tutoriel s’adresse aux développeurs qui doivent chiffrer des fichiers, protéger des secrets applicatifs ou sécuriser un canal de communication sans dépendre d’un service tiers. Aucun prérequis en théorie des nombres n’est nécessaire, mais une base en ligne de commande et en Python vous fera gagner du temps. Chaque commande a été exécutée telle quelle avant publication, et les sorties affichées dans l’article proviennent de ces exécutions réelles, pas d’exemples reconstitués.
Pourquoi le chiffrement RSA reste incontournable en 2026
RSA a perdu du terrain face aux courbes elliptiques pour l’échange de clés dans TLS, c’est vrai. La RFC de TLS 1.3 a retiré le mode d’échange de clés RSA pur du protocole, ne conservant que l’authentification par certificat RSA couplée à un échange Diffie-Hellman éphémère. TLS 1.2, encore présent sur une partie du parc applicatif en France et en Europe, autorise toujours l’échange de clés RSA classique, sans confidentialité persistante. Mais en dehors de TLS, RSA reste la colonne vertébrale du chiffrement de fichiers, du chiffrement d’e-mails avec GPG, de la protection des sauvegardes et de nombreux systèmes de gestion de secrets d’entreprise.
La raison tient à sa simplicité conceptuelle et à sa portabilité. Une clé publique RSA se colle dans un fichier .pem, se partage par e-mail ou se publie sur un serveur de clés, et n’importe quel outil compatible PKCS#1 sait s’en servir. Pas besoin de négocier une courbe, pas de dépendance à un standard post-quantique encore jeune. C’est cette universalité qui explique pourquoi RSA continue d’apparaître dans les nouveaux projets malgré la pression du calcul quantique, sujet que nous creusons plus loin dans cet article.
Sur le terrain, en France comme ailleurs en Europe, RSA se retrouve encore dans les scripts de sauvegarde chiffrée, les outils de signature de paquets logiciels, les intégrations SFTP historiques et une bonne partie des interfaces d’API tierces qui exigent un chiffrement asymétrique compatible OpenSSL sans configuration exotique côté client. Remplacer ces intégrations du jour au lendemain coûterait cher pour un gain de sécurité marginal tant que les tailles de clés respectent les seuils recommandés. L’enjeu réel n’est donc pas d’abandonner RSA en urgence, mais de savoir précisément quand et comment le faire évoluer.
Comprendre l’échange de clés RSA et le chiffrement hybride RSA+AES
RSA repose sur un problème mathématique simple à énoncer et coûteux à casser : factoriser un très grand nombre entier, produit de deux nombres premiers. La clé publique contient ce produit (le modulus) et un exposant public. La clé privée contient l’exposant privé, calculable uniquement si l’on connaît les deux facteurs premiers d’origine. Chiffrer avec la clé publique, déchiffrer avec la clé privée : c’est le principe de base, exploité depuis la publication de l’algorithme par Rivest, Shamir et Adleman en 1977.
L’exposant public 65537 (0x10001 en hexadécimal) que nous utilisons dans ce tutoriel n’est pas arbitraire. Ce nombre premier de Fermat offre un bon compromis : assez grand pour résister aux attaques exploitant de petits exposants publics, assez petit pour garder les opérations de chiffrement rapides. Des exposants comme 3 ont longtemps circulé dans du code ancien, mais ils exposent à des attaques bien documentées quand le padding est mal implémenté. Toutes les bibliothèques modernes, dont pyca/cryptography et OpenSSL, imposent 65537 par défaut, et il n’y a aucune raison de s’en écarter.
Le schéma d’enveloppe : pourquoi on ne chiffre jamais les données directement avec RSA
RSA ne peut chiffrer qu’un bloc de données plus petit que sa taille de clé, moins la marge consommée par le padding. Avec une clé de 3072 bits et un padding OAEP-SHA256, la limite tourne autour de 318 octets par bloc. Chiffrer un fichier entier bloc par bloc serait d’une lenteur insupportable comparé à un chiffreur symétrique. La solution standard, appelée chiffrement par enveloppe (envelope encryption), sépare les rôles : on génère une clé de session AES-256 aléatoire, on chiffre les données réelles avec cette clé AES (rapide, quel que soit le volume), puis on chiffre uniquement cette petite clé de session avec RSA. Le destinataire déchiffre d’abord la clé de session avec sa clé privée RSA, puis s’en sert pour déchiffrer le contenu. C’est exactement ce que fait TLS en interne, et c’est ce que nous allons reproduire pas à pas.
Prérequis : outils, versions et environnement de travail
Avant de lancer la première commande, vérifiez que votre environnement correspond aux versions ci-dessous. Les exemples de ce tutoriel ont été exécutés et validés avec ces outils.
| Outil | Version recommandée (2026) | Rôle dans le tutoriel |
|---|---|---|
| Python | 3.12 ou supérieur | Exécution des scripts de chiffrement hybride |
| pyca/cryptography | 50.0.0 (dernière stable, publiée le 31/07/2026) | Bibliothèque RSA, AES-GCM et OAEP en Python |
| OpenSSL | 3.5.x (branche LTS, fin de support avril 2030) | Génération de clés et chiffrement en ligne de commande |
| pip | 24.x ou supérieur | Installation de la bibliothèque cryptography |
| Terminal Linux/macOS ou WSL2 | N/A | Exécution des commandes shell |
Si votre distribution embarque encore OpenSSL 3.0, notez que cette branche atteint sa fin de vie le 7 septembre 2026 selon le calendrier officiel du projet OpenSSL. Migrez vers 3.5 LTS avant cette date pour continuer à recevoir les correctifs de sécurité. La branche 4.0, sortie en juin 2026, existe aussi mais reste encore peu déployée en production au moment de la rédaction.
Pourquoi Python 3.12 précisément ? Les versions plus anciennes fonctionnent aussi avec pyca/cryptography, mais 3.12 apporte des gains de performance mesurables sur les opérations cryptographiques intensives et bénéficie encore d’un support de sécurité actif. Si votre parc tourne sous Python 3.9 ou 3.10, le code de ce tutoriel reste compatible, seule la vitesse d’exécution variera légèrement. Évitez en revanche toute version antérieure à 3.9, écartée du support de sécurité officiel.
Installez la bibliothèque Python avec la commande suivante :
pip install --upgrade cryptography
python3 -c "import cryptography; print(cryptography.__version__)"
Vérifiez aussi votre version d’OpenSSL, en particulier si vous prévoyez de générer des certificats pour un usage en production :
openssl version
# Sortie attendue (exemple) : OpenSSL 3.5.7 9 Jun 2026
Étapes 1 à 3 : générer et protéger la paire de clés RSA
- Étape 1: Choisir la taille de clé. En 2026, 3072 bits est le minimum raisonnable pour un nouveau projet (voir le tableau des recommandations plus bas). Évitez 2048 bits pour tout ce qui doit rester confidentiel au-delà de 2030.
- Étape 2: Générer la clé privée avec OpenSSL, exposant public 65537 (valeur standard, rapide à vérifier et résistante aux attaques connues sur les petits exposants).
- Étape 3: Extraire la clé publique correspondante dans un fichier séparé, à distribuer sans risque.
# Génère une clé privée RSA 3072 bits
openssl genpkey -algorithm RSA -pkeyopt rsa_keygen_bits:3072 -out rsa_private.pem
# Restreint les permissions du fichier (lecture propriétaire uniquement)
chmod 600 rsa_private.pem
# Extrait la clé publique
openssl pkey -in rsa_private.pem -pubout -out rsa_public.pem
# Vérifie la taille de clé générée
openssl pkey -in rsa_private.pem -noout -text | head -1
Sortie obtenue lors du test de ce tutoriel :
Private-Key: (3072 bit, 2 primes)
Le fichier de clé privée pèse environ 2,4 Ko une fois généré, la clé publique environ 620 octets. Ne committez jamais le fichier rsa_private.pem dans un dépôt Git, même privé. Ajoutez-le systématiquement à votre .gitignore avant la première génération, pas après.
Étapes 4 à 6 : chiffrer un message avec RSA-OAEP et AES-256-GCM
- Étape 4: Générer une clé de session AES-256 aléatoire et un nonce, avec un générateur cryptographiquement sûr (os.urandom, jamais random.random).
- Étape 5: Chiffrer les données réelles avec AES-256-GCM, qui fournit à la fois confidentialité et intégrité (contrairement à un mode CBC nu).
- Étape 6: Chiffrer la clé de session AES avec la clé publique RSA, en utilisant le padding OAEP-SHA256, jamais PKCS#1 v1.5 pour du code neuf.
import os
from cryptography.hazmat.primitives.asymmetric import padding as asym_padding
from cryptography.hazmat.primitives import hashes, serialization
from cryptography.hazmat.primitives.ciphers.aead import AESGCM
# Charge la clé publique RSA générée à l'étape 3
with open("rsa_public.pem", "rb") as f:
public_key = serialization.load_pem_public_key(f.read())
message = b"Rapport confidentiel : migration post-quantique T3 2026"
# Étape 4 : clé de session AES-256 + nonce aléatoires
aes_key = os.urandom(32)
nonce = os.urandom(12)
# Étape 5 : chiffrement du message avec AES-256-GCM
ciphertext = AESGCM(aes_key).encrypt(nonce, message, associated_data=None)
# Étape 6 : chiffrement de la clé de session avec RSA-OAEP/SHA-256
encrypted_aes_key = public_key.encrypt(
aes_key,
asym_padding.OAEP(
mgf=asym_padding.MGF1(algorithm=hashes.SHA256()),
algorithm=hashes.SHA256(),
label=None,
),
)
print("Clé AES chiffrée (RSA-OAEP):", len(encrypted_aes_key), "octets")
print("Message chiffré (AES-256-GCM):", len(ciphertext), "octets")
Résultat obtenu lors de l’exécution réelle de ce script, avec une clé RSA 3072 bits :
Clé AES chiffrée (RSA-OAEP): 384 octets
Message chiffré (AES-256-GCM): 71 octets
Remarquez la disproportion : la clé AES chiffrée pèse 384 octets, alors que le message chiffré n’en pèse que 71. C’est normal, RSA produit toujours un bloc de sortie de la taille de son modulus (3072 bits = 384 octets), quelle que soit la taille de l’entrée. C’est justement pour cette raison qu’on ne chiffre jamais un gros fichier directement avec RSA.
Étapes 7 à 9 : déchiffrer et vérifier l’intégrité des données
- Étape 7: Charger la clé privée RSA côté destinataire.
- Étape 8: Déchiffrer la clé de session AES avec RSA-OAEP.
- Étape 9: Déchiffrer le message avec AES-256-GCM, qui échoue automatiquement si le texte chiffré a été altéré (protection d’intégrité intégrée au mode GCM).
from cryptography.hazmat.primitives.asymmetric import padding as asym_padding
from cryptography.hazmat.primitives import hashes, serialization
from cryptography.hazmat.primitives.ciphers.aead import AESGCM
# Étape 7 : charge la clé privée
with open("rsa_private.pem", "rb") as f:
private_key = serialization.load_pem_private_key(f.read(), password=None)
# Étape 8 : déchiffre la clé de session AES
decrypted_aes_key = private_key.decrypt(
encrypted_aes_key,
asym_padding.OAEP(
mgf=asym_padding.MGF1(algorithm=hashes.SHA256()),
algorithm=hashes.SHA256(),
label=None,
),
)
# Étape 9 : déchiffre le message et vérifie l'intégrité (GCM lève une exception si altéré)
plaintext = AESGCM(decrypted_aes_key).decrypt(nonce, ciphertext, associated_data=None)
print("Message déchiffré:", plaintext.decode())
assert plaintext == message
print("Intégrité vérifiée")
Exécuté tel quel, ce bloc affiche Message déchiffré: Rapport confidentiel : migration post-quantique T3 2026 suivi de Intégrité vérifiée. Si vous modifiez ne serait-ce qu’un octet du ciphertext avant le déchiffrement, AESGCM lève une exception InvalidTag plutôt que de renvoyer des données corrompues silencieusement. C’est un comportement volontaire, ne le contournez jamais avec un bloc try/except vide en production.
Étapes 10 à 12 : intégrer RSA dans un flux OpenSSL en ligne de commande
Pour des scripts shell, des pipelines CI/CD ou du dépannage rapide sans écrire de Python, OpenSSL propose l’utilitaire pkeyutl qui reproduit le même schéma OAEP.
- Étape 10: Générer une clé de session brute côté ligne de commande.
- Étape 11: Chiffrer cette clé avec pkeyutl et le padding OAEP-SHA256, pour rester compatible avec le code Python des étapes précédentes.
- Étape 12: Déchiffrer et comparer avec la commande diff pour confirmer l’aller-retour.
# Étape 10 : génère une clé de session de 32 octets
openssl rand -out session_key.bin 32
# Étape 11 : chiffre la clé de session avec RSA-OAEP/SHA-256
openssl pkeyutl -encrypt -pubin -inkey rsa_public.pem \
-in session_key.bin -out session_key.enc \
-pkeyopt rsa_padding_mode:oaep -pkeyopt rsa_oaep_md:sha256
# Étape 12 : déchiffre et vérifie
openssl pkeyutl -decrypt -inkey rsa_private.pem \
-in session_key.enc -out session_key.dec \
-pkeyopt rsa_padding_mode:oaep -pkeyopt rsa_oaep_md:sha256
diff session_key.bin session_key.dec && echo "Aller-retour OK"
Testé sur une clé RSA 3072 bits, le fichier session_key.enc pèse exactement 384 octets, la commande diff ne remonte aucune différence et le script affiche “Aller-retour OK”. Cette même approche s’utilise pour protéger une clé de déchiffrement de sauvegarde, un secret Ansible Vault ou une clé de chiffrement de disque avant de la stocker dans un coffre-fort partagé.
L’avantage de cette approche en ligne de commande, c’est qu’elle s’intègre directement dans un pipeline CI/CD sans dépendance Python. Un job GitLab CI ou GitHub Actions peut chiffrer un artefact de build avec ces trois commandes, sans installer de bibliothèque supplémentaire, tant qu’OpenSSL est déjà présent sur l’image de base. C’est souvent le cas dans les environnements Alpine ou Debian slim utilisés en production.
Tailles de clés RSA recommandées par le NIST et l’ANSSI en 2026
Le choix de la taille de clé n’est pas cosmétique, il détermine votre marge de sécurité face à l’amélioration continue des capacités de calcul (classique, pas encore quantique à cette échelle). Voici où en sont les principaux référentiels au 20 août 2026.
| Référentiel | Recommandation | Échéance |
|---|---|---|
| NIST SP 800-131A Rev. 2 | Modulus RSA ≥ 2048 bits (sécurité minimale 112 bits) | En vigueur |
| NIST (référence 128 bits de sécurité) | RSA-3072 recommandé comme minimum pour les nouveaux systèmes | En vigueur |
| ENISA / EUCC (mécanismes cryptographiques agréés) | RSA entre 1900 et 3000 bits toléré à titre transitoire seulement | Tolérance jusqu’au 31 décembre 2025 |
| Cadre européen cité par les autorités espagnoles (CCN) | RSA ≥ 3000 bits obligatoire pour tout usage exclusif | À partir du 1ᵉʳ janvier 2027 |
| BSI (Allemagne, TR-02102-1) | RSA ≥ 3000 bits recommandé pour les nouveaux déploiements | En vigueur |
| NIST IR 8547 (trajectoire post-quantique) | RSA-2048 classé obsolète en 2030, interdit dans les référentiels FIPS en 2035 | 2030 / 2035 |
La France suit une trajectoire cohérente avec ce mouvement européen. L’ANSSI a d’ailleurs confirmé la fin des certifications s’appuyant uniquement sur RSA classique à partir de 2027, un sujet que nous détaillons dans notre article sur la fin des certifications ANSSI sans PQC. Concrètement, pour un projet démarré aujourd’hui, retenez trois chiffres : 3072 bits comme plancher, 4096 bits si vous avez de la marge de calcul et un horizon de conservation des données au-delà de 2035, et une vigilance active sur les annonces ANSSI et NIST d’ici 2030.
Pour donner un ordre de grandeur du coût de calcul, voici des temps de génération de clé mesurés sur une machine de test à 8 cœurs, avec OpenSSL 3.0 :
| Taille de clé | Temps de génération mesuré | Sécurité approximative |
|---|---|---|
| 2048 bits | 0,42 s | 112 bits |
| 3072 bits | 0,73 s | 128 bits |
| 4096 bits | 0,93 s | ~150 bits |
La génération de clé ne se fait qu’une fois, ces temps ne pèsent donc jamais sur les performances d’une application en production. C’est le chiffrement/déchiffrement répété qui compte, et c’est justement ce que le schéma hybride optimise en confiant le gros du travail à AES.
Erreurs courantes à éviter avec le chiffrement RSA
La plupart des incidents liés à RSA ne viennent pas de l’algorithme lui-même, mais de la façon dont les équipes l’implémentent. Un algorithme mathématiquement solide reste vulnérable si son intégration laisse passer une erreur de padding, une clé mal protégée ou une dépendance jamais mise à jour. Voici les cinq pièges les plus fréquents observés dans des audits de code récents.
- Utiliser le padding PKCS#1 v1.5 pour du code neuf. Ce padding, plus ancien, reste vulnérable aux attaques de type oracle de padding dans certaines configurations mal isolées. Préférez systématiquement OAEP pour le chiffrement.
- Chiffrer directement les données avec RSA au lieu d’une clé de session. Au-delà de la limite de taille de bloc, cette pratique expose à des schémas d’attaque par déduction sur des messages structurés ou répétitifs.
- Réutiliser le même nonce AES-GCM avec la même clé. Un nonce réutilisé casse totalement la confidentialité du mode GCM. Générez toujours un nonce aléatoire de 12 octets par opération de chiffrement.
- Stocker la clé privée sans chiffrement ni permissions restreintes. Un fichier .pem en clair, lisible par tous les utilisateurs du système, annule tout le bénéfice de RSA. Protégez-le avec une passphrase et des permissions 600 au minimum.
- Garder une bibliothèque cryptographique obsolète. Deux correctifs de sécurité ont touché pyca/cryptography au premier semestre 2026, l’un en février (CVE-2026-26007, corrigé en version 46.0.5) et l’autre plus tard dans l’année (CVE-2026-39892, corrigé en 46.0.7). Une dépendance figée depuis 18 mois est un risque, pas une économie de temps.
Dépannage : résoudre les problèmes fréquents
Voici les erreurs les plus souvent rencontrées en suivant ce tutoriel, avec leur cause et leur correction. Gardez cette liste sous la main lors de votre première implémentation, la majorité des blocages viennent d’un de ces huit cas.
- ValueError: Ciphertext length must be equal to key size. Vous tentez de déchiffrer avec une clé privée qui ne correspond pas à la clé publique utilisée pour chiffrer. Vérifiez que rsa_private.pem et rsa_public.pem proviennent bien de la même paire.
- cryptography.exceptions.InvalidTag lors du déchiffrement AES-GCM. Le nonce ou le ciphertext ont été altérés, tronqués, ou vous utilisez le mauvais nonce. Confirmez que vous transmettez bien le nonce généré à l’étape 4, pas un nonce recréé à la volée.
- openssl: Error setting RSA padding mode. Votre version d’OpenSSL est trop ancienne pour l’option rsa_padding_mode:oaep sur cette commande. Mettez à jour vers OpenSSL 1.1.1 ou supérieur, idéalement la branche 3.5 LTS.
- Permission denied en lisant rsa_private.pem. C’est le comportement attendu si vous avez appliqué chmod 600 et que vous exécutez le script sous un autre utilisateur. Exécutez le script avec le même compte que celui qui a généré la clé, ou ajustez les permissions consciemment.
- La clé publique refuse de charger avec load_pem_public_key. Vérifiez que le fichier commence bien par —–BEGIN PUBLIC KEY—– et non par —–BEGIN RSA PRIVATE KEY—–. Une confusion de fichiers est l’erreur la plus banale, et la plus fréquente en debug.
- pip install cryptography échoue avec une erreur de compilation Rust. Les versions récentes de la bibliothèque embarquent des composants Rust. Installez rustc et cargo via rustup, ou utilisez une roue précompilée correspondant à votre plateforme.
- Le script Python est lent au démarrage sur une clé 4096 bits. C’est attendu, la génération de clé RSA 4096 bits prend presque le double de temps qu’une clé 3072 bits. Générez la clé une seule fois et réutilisez-la, ne la régénérez jamais à chaque exécution.
- diff signale une différence entre session_key.bin et session_key.dec. Vérifiez que vous utilisez bien les mêmes paramètres OAEP (rsa_oaep_md:sha256) au chiffrement et au déchiffrement. Un mismatch de fonction de hachage MGF fait échouer silencieusement l’opération dans certaines versions d’OpenSSL.
Bonnes pratiques avancées et durcissement de la sécurité
Une fois le schéma de base opérationnel, plusieurs ajustements renforcent la posture de sécurité sans complexité supplémentaire majeure. Chiffrez systématiquement votre clé privée au repos avec une passphrase, via serialization.BestAvailableEncryption en Python ou l’option -aes256 lors de la génération OpenSSL. Faites tourner vos clés RSA selon un calendrier défini, un an pour des secrets sensibles, plus court pour des environnements à haut risque, et documentez la procédure de rotation avant d’en avoir besoin en urgence. Testez cette procédure de rotation au moins une fois en environnement de préproduction : une équipe qui découvre les frictions d’une rotation de clé pour la première fois en pleine urgence de sécurité perd un temps précieux qu’une répétition en amont aurait évité.
Ajoutez des données authentifiées associées (associated_data) à votre appel AESGCM.encrypt lorsque le contexte s’y prête, par exemple un identifiant de session ou un numéro de version de format. Cela lie cryptographiquement le ciphertext à son contexte d’usage et bloque certaines attaques de rejeu ou de substitution de message entre deux flux différents. Enfin, centralisez la gestion des clés privées dans un HSM ou un service de gestion de secrets (Vault, AWS KMS, Azure Key Vault) dès que le projet dépasse le stade du prototype : un fichier .pem qui traîne sur un poste de développeur reste le vecteur de fuite le plus documenté dans les rapports d’incident 2025-2026.
Journalisez chaque opération de déchiffrement sensible, sans jamais logger la clé ni le texte en clair, uniquement un horodatage, un identifiant d’opération et le résultat (succès ou échec). Ce simple ajout transforme un incident silencieux en alerte exploitable. Si votre équipe gère plusieurs paires de clés, ajoutez un identifiant de version dans les métadonnées du fichier chiffré : cela évite de deviner à l’aveugle quelle clé privée essayer lors d’une opération de reprise après incident.
Cas d’usage concrets en entreprise
Le schéma que vous venez de construire ne reste pas théorique. Il correspond à des besoins récurrents que rencontrent la plupart des équipes techniques, avec des variantes selon le contexte réglementaire.
- Chiffrement de sauvegardes avant envoi vers un stockage tiers. Une sauvegarde de base de données chiffrée en local avec AES-256, dont la clé de session est protégée par RSA, peut transiter vers un stockage cloud externe sans exposer les données même en cas de compromission du compte de stockage.
- Chiffrement d’e-mails et de pièces jointes sensibles. GPG s’appuie sur le même principe d’enveloppe que celui détaillé dans cet article. Notre guide GPG couvre spécifiquement ce cas d’usage pour la messagerie professionnelle.
- Protection de secrets applicatifs au repos. Un fichier de configuration contenant des identifiants de base de données peut être chiffré côté CI/CD, avec la clé privée RSA stockée uniquement dans le coffre-fort de secrets de la plateforme de déploiement, jamais dans le dépôt de code.
- Conformité RGPD pour les données de santé et les données financières. Le secteur de la e-santé français, soumis à l’hébergement de données de santé (HDS), exige fréquemment un chiffrement documenté au repos. Un schéma RSA-3072 + AES-256-GCM, avec rotation de clés tracée, répond à cette exigence sans complexité d’infrastructure supplémentaire.
- Signature et vérification de paquets logiciels internes. Même si la signature proprement dite relève de RSA en mode signature plutôt que chiffrement, la même paire de clés generée dans ce tutoriel peut signer des artefacts de build, une pratique de plus en plus attendue par les audits de chaîne d’approvisionnement logicielle depuis l’entrée en vigueur du Cyber Resilience Act européen.
Dans chacun de ces scénarios, le choix technique reste le même : générer une clé de session symétrique, chiffrer les données avec cette clé, puis protéger uniquement la clé avec RSA. Ce qui change d’un cas à l’autre, c’est la politique de rotation des clés, l’emplacement de stockage de la clé privée et le niveau d’audit exigé par votre secteur d’activité. Une startup qui chiffre des exports CSV internes n’a pas les mêmes contraintes qu’un établissement de santé soumis à l’hébergement de données de santé, mais le code de base reste identique.
RSA face au calcul quantique : faut-il migrer vers ML-KEM maintenant
La question revient dans toutes les revues d’architecture depuis que le NIST a finalisé ses standards post-quantiques. FIPS 203 (ML-KEM), FIPS 204 (ML-DSA) et FIPS 205 (SLH-DSA) sont désormais des standards publiés, pas des brouillons, et le NIST fixe une trajectoire claire : RSA-2048 classé obsolète en 2030, interdit dans les référentiels FIPS à partir de 2035. La bibliothèque pyca/cryptography embarque d’ailleurs ML-KEM et ML-DSA nativement depuis sa version 48, installable par un simple pip install selon Trail of Bits.
Pour un nouveau projet à durée de vie longue (archivage, certificats racine, secrets destinés à rester confidentiels après 2035), le choix raisonnable consiste à déployer un schéma hybride classique + post-quantique dès maintenant, RSA ou ECDH combiné à ML-KEM, plutôt que d’attendre une migration complète en urgence. Nous détaillons cette implémentation pas à pas dans notre tutoriel dédié à ML-KEM, et notre comparatif RSA/ECC face à la cryptographie post-quantique chiffre précisément l’écart de performance entre les deux approches. Pour un projet à courte durée de vie (session TLS, jeton temporaire), RSA-3072 avec OAEP reste un choix défendable en 2026, tant que la veille sur les annonces ANSSI reste active.
La bonne nouvelle, c’est que migrer le code que vous venez d’écrire vers un schéma post-quantique ne demande pas de tout réécrire. La structure du chiffrement par enveloppe reste identique : seule l’étape de protection de la clé de session change de mécanisme, RSA-OAEP cédant la place à un encapsulement ML-KEM. Si vous concevez aujourd’hui un nouveau service avec le schéma RSA de ce tutoriel, isolez cette étape dans une fonction dédiée dès le départ. Vous gagnerez un temps précieux le jour où la migration post-quantique deviendra une exigence de conformité plutôt qu’une bonne pratique anticipée.
Projet complet : un script Python de bout en bout
Voici l’assemblage complet des étapes précédentes dans un seul fichier exécutable, prêt à copier-coller. Il génère les clés si elles n’existent pas, chiffre un message, le déchiffre, puis vérifie l’intégrité.
import os
from cryptography.hazmat.primitives.asymmetric import rsa, padding as asym_padding
from cryptography.hazmat.primitives import hashes, serialization
from cryptography.hazmat.primitives.ciphers.aead import AESGCM
PRIVATE_KEY_PATH = "rsa_private.pem"
PUBLIC_KEY_PATH = "rsa_public.pem"
def generate_keys_if_missing(key_size=3072):
if os.path.exists(PRIVATE_KEY_PATH):
return
private_key = rsa.generate_private_key(public_exponent=65537, key_size=key_size)
with open(PRIVATE_KEY_PATH, "wb") as f:
f.write(private_key.private_bytes(
encoding=serialization.Encoding.PEM,
format=serialization.PrivateFormat.PKCS8,
encryption_algorithm=serialization.NoEncryption(),
))
with open(PUBLIC_KEY_PATH, "wb") as f:
f.write(private_key.public_key().public_bytes(
encoding=serialization.Encoding.PEM,
format=serialization.PublicFormat.SubjectPublicKeyInfo,
))
os.chmod(PRIVATE_KEY_PATH, 0o600)
def hybrid_encrypt(message: bytes, public_key):
aes_key = os.urandom(32)
nonce = os.urandom(12)
ciphertext = AESGCM(aes_key).encrypt(nonce, message, associated_data=None)
encrypted_key = public_key.encrypt(
aes_key,
asym_padding.OAEP(
mgf=asym_padding.MGF1(algorithm=hashes.SHA256()),
algorithm=hashes.SHA256(),
label=None,
),
)
return encrypted_key, nonce, ciphertext
def hybrid_decrypt(encrypted_key, nonce, ciphertext, private_key):
aes_key = private_key.decrypt(
encrypted_key,
asym_padding.OAEP(
mgf=asym_padding.MGF1(algorithm=hashes.SHA256()),
algorithm=hashes.SHA256(),
label=None,
),
)
return AESGCM(aes_key).decrypt(nonce, ciphertext, associated_data=None)
if __name__ == "__main__":
generate_keys_if_missing()
with open(PUBLIC_KEY_PATH, "rb") as f:
public_key = serialization.load_pem_public_key(f.read())
with open(PRIVATE_KEY_PATH, "rb") as f:
private_key = serialization.load_pem_private_key(f.read(), password=None)
message = b"Rapport confidentiel : migration post-quantique T3 2026"
encrypted_key, nonce, ciphertext = hybrid_encrypt(message, public_key)
print("Clé chiffrée:", len(encrypted_key), "octets | Message chiffré:", len(ciphertext), "octets")
plaintext = hybrid_decrypt(encrypted_key, nonce, ciphertext, private_key)
assert plaintext == message
print("Déchiffrement réussi:", plaintext.decode())
Lancé une première fois, ce script crée les fichiers rsa_private.pem et rsa_public.pem dans le dossier courant, puis affiche Clé chiffrée: 384 octets | Message chiffré: 71 octets suivi de Déchiffrement réussi: Rapport confidentiel : migration post-quantique T3 2026. Relancez-le une seconde fois : les clés existantes sont réutilisées, seule l’opération de chiffrement/déchiffrement s’exécute à nouveau. C’est la base à partir de laquelle brancher un vrai flux de fichiers, en remplaçant le message en dur par une lecture de fichier binaire.
Questions fréquentes sur le chiffrement RSA
RSA est-il encore sûr en 2026 ?
Oui, à condition d’utiliser une clé d’au moins 3072 bits et le padding OAEP. Le NIST situe la dépréciation de RSA-2048 en 2030, pas avant, et son interdiction dans les référentiels FIPS en 2035.
Quelle taille de clé RSA choisir pour un nouveau projet ?
3072 bits au minimum en 2026. Montez à 4096 bits si vos données doivent rester confidentielles après 2035 ou si un référentiel de conformité européen l’exige explicitement.
Pourquoi ne pas chiffrer directement un fichier avec RSA ?
RSA ne chiffre qu’un bloc de données plus petit que sa taille de clé. Pour un fichier de plusieurs mégaoctets, il faut passer par un chiffrement hybride : AES pour les données, RSA pour protéger uniquement la clé AES.
Quelle est la différence entre OAEP et PKCS#1 v1.5 ?
OAEP est le padding moderne, résistant aux attaques par oracle qui ont touché certaines implémentations PKCS#1 v1.5 par le passé. Utilisez OAEP pour tout chiffrement RSA neuf, gardez PKCS#1 v1.5 uniquement pour la compatibilité avec des systèmes existants que vous ne pouvez pas modifier.
Faut-il migrer vers ML-KEM dès maintenant ?
Pour des données à conserver confidentielles au-delà de 2035, un schéma hybride RSA/ECDH + ML-KEM est recommandé dès aujourd’hui. Pour des usages à courte durée de vie, RSA-3072 reste acceptable en 2026, avec une veille active sur les recommandations ANSSI.
TLS 1.3 utilise-t-il encore RSA pour l’échange de clés ?
Non. TLS 1.3 a retiré l’échange de clés RSA du protocole et ne conserve RSA que pour l’authentification par certificat, l’échange de clés passant par Diffie-Hellman éphémère. TLS 1.2 autorise encore l’échange de clés RSA classique, sans confidentialité persistante.
Quelle bibliothèque Python utiliser pour RSA en 2026 ?
pyca/cryptography reste la référence, avec sa version 50.0.0 publiée fin juillet 2026. Évitez les bibliothèques non maintenues depuis plus d’un an pour tout usage en production.
Comment protéger une clé privée RSA sur disque ?
Restreignez les permissions du fichier à 600, chiffrez-le avec une passphrase via BestAvailableEncryption en Python (ou -aes256 avec OpenSSL), et pour un usage en production, préférez un HSM ou un gestionnaire de secrets à un simple fichier .pem local.
Peut-on utiliser RSA et AES avec des bibliothèques différentes ?
Oui, tant que les deux implémentations respectent le même standard de padding (OAEP-SHA256 pour RSA, GCM pour AES) et la même taille de clé. Un chiffrement réalisé avec OpenSSL en ligne de commande se déchiffre sans problème avec le script Python de ce tutoriel, comme le montrent les étapes 10 à 12.
Combien de temps prend la génération d’une clé RSA en production ?
Sur un serveur standard, comptez moins d’une seconde pour une clé 3072 bits, un peu moins d’une seconde pour 4096 bits. Cette opération ne se déroule qu’une seule fois par paire de clés, elle n’a donc aucun impact sur les performances de votre application au quotidien.
Sources et lectures complémentaires
- NIST SP 800-131A Rev. 2: Transitioning the Use of Cryptographic Algorithms and Key Lengths
- NIST FIPS 203: Module-Lattice-Based Key-Encapsulation Mechanism Standard
- Changelog officiel de pyca/cryptography
- Page PyPI de la bibliothèque cryptography
- Stratégie de versions et fin de vie d’OpenSSL
- BSI TR-02102-1: Cryptographic Mechanisms (Allemagne)
- ENISA: EUCC Guidelines on Cryptography
- ANSSI: Mécanismes cryptographiques, règles et recommandations
Related Coverage
- Cryptographie Post-Quantique : ML-KEM en 12 Étapes
- RSA/ECC vs Post-Quantique : ML-KEM 2,4x Plus Rapide
- ECDSA vs RSA : Signatures 9,5x Plus Rapides
- Europe : ENISA Bannit RSA Sous 3000 Bits en 2026
- Post-Quantique : ANSSI Bannit le RSA Seul dès 2027
- GPG : chiffrer fichiers et emails, 12 étapes
- Cryptographie et fonctions de hachage : le socle de la confiance numérique




