ITSkillsCenter
Cybersécurité

Chiffrer et signer en RSA pas-à-pas — OAEP, PSS et chiffrement hybride avec AES

17 دقائق للقراءة

Le RSA reste, plus de quarante ans après sa publication par Rivest, Shamir et Adleman, l’algorithme de chiffrement asymétrique le plus déployé au monde. C’est lui qui sert au handshake initial de TLS, à la signature des certificats X.509, à la signature des paquets debian/rpm, à l’authentification des emails par DKIM, et à l’authentification SSH historique avant la généralisation d’ed25519. Comprendre comment l’utiliser correctement reste utile en 2026 — pour les cas où l’asymétrie est nécessaire (chiffrement vers un destinataire qui n’est pas en ligne, signature vérifiable par tous), et parce qu’on en trouve partout dans le code legacy. Ce tutoriel propose une démarche en huit étapes pour générer une paire RSA-3072, chiffrer une donnée, signer un fichier et vérifier la signature, en OpenSSL et en Python.

Pour la vue d’ensemble, voir le guide principal : Cryptographie pratique pour développeurs et sysadmins.

Prérequis

  • OpenSSL 3.0+ et un terminal
  • Python 3.10+ et la bibliothèque cryptography
  • Notions du couple clé publique / clé privée
  • 30 minutes

Étape 1 — Quelle taille de clé en 2026

La taille de la clé RSA détermine son niveau de sécurité. RSA-1024 est cassé pratiquement et n’est plus accepté nulle part depuis 2014. RSA-2048 est encore valide pour des usages courants jusqu’aux alentours de 2030 selon le NIST, mais la marge se réduit. RSA-3072 est le choix par défaut recommandé pour les nouveaux projets en 2026 — équivalent à une clé symétrique de 128 bits. RSA-4096 apporte une marge supplémentaire pour des secrets à long terme (signature de root CA, archives chiffrées sur dix ans).

À noter : RSA est plus lent que les algorithmes basés sur les courbes elliptiques (Ed25519, ECDSA) à niveau de sécurité équivalent. Pour un nouveau projet où on a le choix, ECDSA P-256 ou Ed25519 sont souvent préférables. RSA reste pertinent pour la compatibilité avec des écosystèmes anciens et pour les standards qui l’imposent (DKIM, certains modules HSM).

Étape 2 — Générer la paire RSA avec OpenSSL

OpenSSL 3 utilise la sous-commande genpkey moderne (l’ancienne genrsa est dépréciée). Génération d’une clé privée RSA-3072 :

openssl genpkey -algorithm RSA -out cle_privee.pem -pkeyopt rsa_keygen_bits:3072 -aes-256-cbc

Décortiquons. -algorithm RSA impose le type de clé. -pkeyopt rsa_keygen_bits:3072 fixe la taille. -aes-256-cbc chiffre la clé privée avec une phrase secrète qui sera demandée — sans cette option, la clé privée serait stockée en clair sur disque, exposée à toute lecture du fichier.

Extraire la clé publique correspondante :

openssl pkey -in cle_privee.pem -pubout -out cle_publique.pem

La clé publique peut être partagée librement — elle ne permet que de chiffrer ou vérifier, jamais de déchiffrer ou signer. La clé privée doit rester strictement personnelle, protégée par sa phrase secrète, et sauvegardée dans un coffre chiffré (Bitwarden, KeePass, Cryptomator).

Étape 3 — Chiffrer un secret court

RSA chiffre des messages courts — moins que la taille de la clé moins la place du padding. Pour RSA-3072 avec OAEP, on peut chiffrer environ 318 octets maximum. C’est largement suffisant pour transporter une clé symétrique AES-256 (32 octets), ce qui est l’usage standard : RSA chiffre la clé AES, AES chiffre les données. C’est exactement le schéma utilisé par TLS, GPG et la quasi-totalité des protocoles asymétriques pratiques.

Chiffrer un petit secret directement avec OpenSSL :

echo -n "secret transporte" > secret.txt
openssl pkeyutl -encrypt -inkey cle_publique.pem -pubin \
  -pkeyopt rsa_padding_mode:oaep -pkeyopt rsa_oaep_md:sha256 \
  -in secret.txt -out secret.enc

L’option -pkeyopt rsa_padding_mode:oaep est cruciale : OAEP (Optimal Asymmetric Encryption Padding) est le seul padding recommandé en 2026 pour le chiffrement RSA. L’ancien padding PKCS#1 v1.5 est vulnérable aux attaques de type Bleichenbacher et doit être évité dans tout nouveau code. rsa_oaep_md:sha256 impose SHA-256 pour la fonction de hachage interne d’OAEP, et rsa_mgf1_md:sha256 impose la même hash pour MGF1 — sans cette seconde option, certaines versions d’OpenSSL retombent silencieusement sur SHA-1 pour MGF1, ce qui casse l’interopérabilité avec un destinataire qui attend SHA-256 partout.

Pour déchiffrer avec la clé privée :

openssl pkeyutl -decrypt -inkey cle_privee.pem \
  -pkeyopt rsa_padding_mode:oaep -pkeyopt rsa_oaep_md:sha256 \
  -in secret.enc -out secret.dec

OpenSSL demande la phrase secrète qui chiffre la clé privée, déchiffre le ciphertext, et écrit l’original dans secret.dec.

Étape 4 — Le pattern hybride en Python

Pour chiffrer plus que quelques centaines d’octets, on utilise le chiffrement hybride : générer une clé AES aléatoire, chiffrer les données en AES-GCM, chiffrer la clé AES en RSA-OAEP, transmettre l’ensemble. Implementation Python :

import os
from cryptography.hazmat.primitives.asymmetric import rsa, padding
from cryptography.hazmat.primitives import hashes, serialization
from cryptography.hazmat.primitives.ciphers.aead import AESGCM

def chiffrer_hybride(donnees: bytes, cle_pub_pem: bytes) -> bytes:
    cle_pub = serialization.load_pem_public_key(cle_pub_pem)
    cle_aes = AESGCM.generate_key(256)
    nonce = os.urandom(12)
    chiffre_aes = AESGCM(cle_aes).encrypt(nonce, donnees, None)
    chiffre_cle = cle_pub.encrypt(
        cle_aes,
        padding.OAEP(
            mgf=padding.MGF1(algorithm=hashes.SHA256()),
            algorithm=hashes.SHA256(),
            label=None
        )
    )
    # Format de sortie: 2 octets de longueur + clé chiffrée + nonce + chiffré AES
    return len(chiffre_cle).to_bytes(2, 'big') + chiffre_cle + nonce + chiffre_aes

Le code génère une clé AES éphémère, chiffre le payload en AES-GCM, chiffre la clé AES en RSA-OAEP-SHA256, et concatène le tout dans un format autodescriptif. Le destinataire — seul détenteur de la clé privée RSA — peut récupérer la clé AES, puis déchiffrer le payload.

Le déchiffrement symétrique :

def dechiffrer_hybride(donnees: bytes, cle_priv_pem: bytes, phrase: bytes) -> bytes:
    cle_priv = serialization.load_pem_private_key(cle_priv_pem, password=phrase)
    longueur = int.from_bytes(donnees[:2], 'big')
    chiffre_cle = donnees[2:2+longueur]
    nonce = donnees[2+longueur:2+longueur+12]
    chiffre_aes = donnees[2+longueur+12:]
    cle_aes = cle_priv.decrypt(
        chiffre_cle,
        padding.OAEP(
            mgf=padding.MGF1(algorithm=hashes.SHA256()),
            algorithm=hashes.SHA256(),
            label=None
        )
    )
    return AESGCM(cle_aes).decrypt(nonce, chiffre_aes, None)

Ce schéma hybride est exactement ce que fait GPG en interne quand on chiffre asymétriquement, et ce qu’utilisait TLS avant le passage majoritaire à ECDHE. Comprendre le motif rend lisible une grande partie du code de cryptographie réelle.

Étape 5 — Signer un fichier

La signature RSA prouve que le fichier vient bien de la personne qui détient la clé privée et n’a pas été modifié. Elle est essentielle pour les binaires, les paquets, les communiqués officiels, les emails DKIM. Avec OpenSSL, signer un fichier :

openssl dgst -sha256 -sign cle_privee.pem -out rapport.sig rapport.pdf

OpenSSL hashe d’abord le fichier en SHA-256, puis signe le hash avec la clé privée. Le résultat est un fichier de signature de 384 octets (pour RSA-3072) — petit, à transmettre à côté du fichier original. Pour vérifier côté destinataire qui a la clé publique :

openssl dgst -sha256 -verify cle_publique.pem -signature rapport.sig rapport.pdf

La sortie indique Verified OK si la signature correspond au fichier et à la clé publique. Une seule modification d’un octet du fichier ou de la signature produit Verification Failure.

Pour un usage moderne en production, préférer le mode RSA-PSS (Probabilistic Signature Scheme) plutôt que le PKCS#1 v1.5 historique :

openssl dgst -sha256 -sign cle_privee.pem -sigopt rsa_padding_mode:pss \
  -sigopt rsa_pss_saltlen:-1 -out rapport.sig rapport.pdf

RSA-PSS est la signature recommandée par le NIST en 2026, plus robuste face aux attaques théoriques connues sur PKCS#1 v1.5. Tous les outils modernes le supportent.

Étape 6 — Signer et vérifier en Python

Le même mécanisme en Python avec cryptography :

from cryptography.hazmat.primitives.asymmetric import padding
from cryptography.hazmat.primitives import hashes
from cryptography.exceptions import InvalidSignature

def signer(donnees: bytes, cle_priv) -> bytes:
    return cle_priv.sign(
        donnees,
        padding.PSS(
            mgf=padding.MGF1(hashes.SHA256()),
            salt_length=padding.PSS.MAX_LENGTH
        ),
        hashes.SHA256()
    )

def verifier(donnees: bytes, signature: bytes, cle_pub) -> bool:
    try:
        cle_pub.verify(
            signature,
            donnees,
            padding.PSS(
                mgf=padding.MGF1(hashes.SHA256()),
                salt_length=padding.PSS.MAX_LENGTH
            ),
            hashes.SHA256()
        )
        return True
    except InvalidSignature:
        return False

Le pattern try/except autour de verify est essentiel : la bibliothèque lève une exception en cas d’échec, on convertit en booléen pour faciliter l’utilisation. Toujours retourner explicitement False sur exception, jamais ignorer silencieusement.

Étape 7 — Distribuer et révoquer la clé publique

Une fois la paire générée, la clé publique doit être distribuée aux interlocuteurs et la clé privée protégée. Trois méthodes de distribution existent en pratique. La publication directe sur un site personnel ou la signature mail (le destinataire la télécharge) — simple mais on ne garantit pas que le fichier n’a pas été substitué en chemin. La signature par une autorité de confiance (PKI X.509, Let’s Encrypt pour TLS) — la clé publique est dans un certificat signé par une CA reconnue. Le web of trust à la GPG — d’autres utilisateurs signent votre clé publique pour attester de son authenticité.

Préparer aussi le scénario de compromission. Si la clé privée fuite, il faut pouvoir la révoquer — annoncer publiquement qu’elle ne doit plus être utilisée. Pour les certificats X.509, ça passe par une CRL ou OCSP côté CA. Pour GPG, par un certificat de révocation à conserver à part. Pour des paires RSA hors PKI, la révocation manuelle (notification aux interlocuteurs, retrait du site web) reste artisanale — d’où l’intérêt d’une rotation régulière des clés.

Les mathématiques en clair

RSA est, parmi les algorithmes cryptographiques modernes, celui dont les fondations mathématiques sont les plus accessibles à expliquer — et c’est exactement pour cette raison qu’il a été le premier chiffrement asymétrique pratique de l’histoire. Ses ingrédients tiennent en trois noms : Euclide pour les nombres premiers, Fermat pour le petit théorème, et Euler pour la fonction phi. Pas de magie, pas de structure exotique — juste de l’arithmétique modulaire bien orchestrée.

Le secret tient dans deux nombres premiers

Pour générer une paire RSA, on tire au hasard deux grands nombres premiers notés p et q. « Grands » signifie environ 1 536 bits chacun pour une clé RSA-3072 (la moitié de 3 072 bits, puisque n = p × q avec p et q de tailles voisines). On calcule ensuite leur produit n = p × q. Ce nombre n, appelé module, fait alors environ 3 072 bits — d’où le nom de l’algorithme. Une fois n calculé, p et q sont stockés à part dans la clé privée et n est publié dans la clé publique.

La sécurité de RSA repose sur un fait mathématique simple à énoncer mais dur à exploiter : multiplier p et q est rapide, mais retrouver p et q à partir de n seul (la factorisation) est extraordinairement lent dès que n dépasse quelques centaines de bits. Aucun algorithme classique connu ne factorise un module de 3 072 bits en moins de plusieurs millénaires sur tous les ordinateurs de la planète réunis. C’est cette asymétrie de coût entre multiplier et factoriser qui rend RSA utilisable en pratique.

L’exposant public et l’exposant privé

On choisit ensuite un exposant public noté e, un petit nombre premier avec (p-1)(q-1). La valeur standard est e = 65 537 (qui est 2¹⁶ + 1, choisi pour la rapidité de calcul tout en étant assez grand pour résister à certaines attaques anciennes). La paire (n, e) constitue la clé publique.

L’exposant privé noté d est calculé comme l’inverse multiplicatif de e modulo (p-1)(q-1). Concrètement, d est l’unique nombre tel que e × d ≡ 1 (mod (p-1)(q-1)). L’algorithme d’Euclide étendu calcule d en quelques millisecondes une fois p et q connus — et reste impossible à calculer pour qui ne connaît que n.

Chiffrer et déchiffrer en deux exponentiations modulaires

Le chiffrement et le déchiffrement RSA tiennent chacun en une seule formule. Pour chiffrer un message m représenté comme un nombre inférieur à n, on calcule c = m^e mod n. Pour déchiffrer, on calcule m = c^d mod n. La beauté de l’opération vient du théorème d’Euler, qui garantit que m^(e×d) ≡ m (mod n) pour tout m premier avec n. Autrement dit, élever au carré-mille-fois puis élever-au-carré-mille-fois-encore-d’une-autre-manière fait revenir au point de départ — un aller-retour exact garanti par l’arithmétique modulaire.

L’exponentiation modulaire m^e mod n sur des nombres de 3 072 bits prend des millisecondes grâce à l’algorithme d’exponentiation rapide qui exploite la décomposition binaire de l’exposant. Sans cet algorithme (calcul naïf m × m × m × … répété e fois), une seule opération RSA prendrait des années.

Pourquoi OAEP plutôt que la formule brute

Appliquer directement c = m^e mod n sur un message court a un défaut majeur : l’opération est déterministe. Le même message clair produit toujours le même chiffré, ce qui permet à un attaquant qui devine le contenu (« est-ce que c’est OUI ou NON ? ») de chiffrer chacune des hypothèses et comparer. Pire, l’algèbre RSA satisfait des relations multiplicatives qui ouvrent la porte à des attaques par texte clair choisi.

OAEP (Optimal Asymmetric Encryption Padding) résout cela en mélangeant le message clair avec un aléa avant le chiffrement RSA. Mathématiquement, OAEP construit deux séquences pseudo-aléatoires à partir d’un nombre aléatoire r et de fonctions de hachage MGF1-SHA256. La première séquence est XORée avec le message, la deuxième avec r. Le résultat est m’ = (message ⊕ G(r)) || (r ⊕ H(message ⊕ G(r))), qu’on chiffre alors avec RSA classique. À l’arrivée, on déchiffre avec RSA puis on inverse les deux XOR pour récupérer r et message. Cette construction garantit qu’un même message produit des chiffrés différents à chaque appel — propriété appelée chiffrement probabiliste.

Pourquoi PSS pour signer

Signer revient à chiffrer avec la clé privée et vérifier à déchiffrer avec la clé publique — ce qui est mathématiquement symétrique au chiffrement, mais sert à prouver l’origine plutôt qu’à protéger le contenu. Le padding PKCS#1 v1.5 historique pour la signature est déterministe et a montré des failles théoriques. PSS (Probabilistic Signature Scheme) introduit là aussi un aléa : à chaque signature, on tire un sel aléatoire salt, on calcule H = hash(0x0000000000000000 || hash(message) || salt), on construit un masque db = padding || salt, on XORe db avec MGF1(H), et on signe le tout. La vérification est plus complexe mais reproductible. La sécurité de PSS est prouvable sous l’hypothèse RSA — propriété mathématique forte qui manque à PKCS#1 v1.5.

Pourquoi RSA-3072 et pas RSA-1024

La sécurité d’une clé RSA dépend de la difficulté de factoriser n. Le meilleur algorithme classique connu, le crible général de corps de nombres (GNFS), a une complexité sous-exponentielle en la taille de n. En pratique, factoriser un RSA-1024 demande quelques dizaines de millions d’heures-CPU — réalisable par des États ou de gros consortiums. RSA-2048 fait grimper le coût à plusieurs milliards d’heures-CPU, encore théoriquement réalisable à long terme mais inaccessible aujourd’hui. RSA-3072 conserve une marge confortable jusqu’aux années 2030 selon les projections NIST, RSA-4096 jusqu’aux années 2040 environ. La progression n’est pas linéaire : doubler la taille de n ne double pas la sécurité — elle la multiplie par un facteur sous-exponentiel proportionnel à exp((log n)^(1/3)).

Le grand défi à venir est l’algorithme de Shor sur ordinateur quantique : il factoriserait n’importe quel n en un temps polynomial en log n. Les ordinateurs quantiques actuels ne dépassent pas encore quelques milliers de qubits utiles ; factoriser un RSA-3072 demanderait plusieurs millions de qubits stables. Estimation industrielle : entre 10 et 30 ans de marge avant que la menace devienne pratique — d’où l’importance des standards post-quantiques publiés par le NIST en 2024 (ML-KEM, ML-DSA) que les bibliothèques crypto modernes commencent à intégrer.

Étape 8 — Choisir entre RSA et ECC

En 2026, la question se pose à chaque nouveau projet asymétrique. RSA reste pertinent dans plusieurs cas : compatibilité avec un écosystème existant (DKIM, vieux serveurs, modules HSM bridés), exigence d’une norme (eIDAS, certaines régulations bancaires), ou simple familiarité de l’équipe. ECC (courbes elliptiques) — Ed25519 pour la signature, X25519 pour le partage de clé, ECDSA P-256 pour les cas X.509 — apporte des clés plus courtes, des signatures plus rapides et un niveau de sécurité équivalent ou supérieur. Pour un nouveau code en 2026, ECC est généralement le bon choix.

Quel que soit le choix, garder à l’esprit que la cryptographie post-quantique se prépare. Les algorithmes RSA et ECC actuels sont vulnérables à un futur ordinateur quantique de grande taille (algorithme de Shor). Le NIST a publié en 2024 les premiers standards post-quantiques (ML-KEM pour le partage de clé, ML-DSA pour la signature) que les bibliothèques crypto modernes intègrent progressivement. Suivre l’évolution sans paniquer — la transition prendra plusieurs années.

Vérification du livrable

  • La paire RSA-3072 est générée avec clé privée chiffrée par AES-256
  • Le chiffrement utilise OAEP-SHA256, pas PKCS#1 v1.5
  • La signature utilise PSS, pas PKCS#1 v1.5
  • Le pattern hybride RSA + AES fonctionne en aller-retour
  • La clé privée est sauvegardée dans un coffre chiffré

Erreurs fréquentes

ErreurConséquenceSolution
RSA-1024 ou 2048Marge de sécurité insuffisanteRSA-3072 minimum en 2026
Padding PKCS#1 v1.5Vulnérable à BleichenbacherOAEP pour chiffrer, PSS pour signer
Clé privée en clairVol = compromission totaleToujours chiffrer la clé privée à la génération
Chiffrer directement gros fichiersRSA limite à quelques centaines d’octetsChiffrement hybride RSA + AES
Pas de plan de révocationCompromission silencieusePréparer un mécanisme dès la génération

DKIM sur domaines en .sn et signature de communiqués officiels

Trois usages locaux où RSA reste pertinent. La signature de communiqués officiels par une administration, une fédération ou une organisation : la signature détachée prouve l’authenticité d’un document PDF circulant par mail ou WhatsApp et coupe court aux manipulations, dans un contexte où les fausses circulaires se propagent vite sur les groupes professionnels. L’authentification DKIM sur un domaine en .sn ou .ci : le serveur de mail signe les messages sortants avec RSA, le destinataire vérifie via DNS — réduit drastiquement le risque que les mails du domaine soient marqués spam, particulièrement utile pour une PME qui prospecte hors de la sous-région. Le chiffrement de paquets de configuration distribués par script à plusieurs serveurs : un même paquet peut être chiffré une fois et déchiffré par chaque serveur disposant de sa clé privée individuelle — pratique pour les déploiements à plusieurs sites entre Dakar, Thiès et Saint-Louis.

Tutoriels frères

Pour aller plus loin

Sources et références

Sponsoriser ce contenu

Cet emplacement est à vous

Position premium en fin d'article — c'est l'instant où les lecteurs sont le plus engagés. Réservez cet espace pour votre marque, votre formation ou votre offre.

Tarifs sur demande
Recevoir nos tarifs
Publicité