Cette série de travaux a pour objectif de vous familiariser avec les fonctions cryptographiques de base proposées par OpenSSL en ligne de commande. Vous découvrirez progressivement les différentes techniques de chiffrement et d'authentification, depuis les concepts fondamentaux jusqu'aux mécanismes plus complexes d'une infrastructure à clés publiques. Une certaine concentration est requise pour prendre le temps d'analyser certaines commandes complexes et les mécanismes associés.
Ce TP fait suite au cours sur la cryptographie. Même si une bonne partie peut être réalisée en solo sur une machine GNU/Linux en mode console, il est prévu pour être réalisé en groupe, tous les utilisateurs connectés à un serveur unique avec un répertoire accessible par tout le monde (ce sera /var/public
) et sur lequel un administrateur (root) a déployé une autorité locale de certification (CA) et pourra gérer les demandes de signature de certificat (CSR) de chaque utilisateur. Les instructions spécifiques pour l'administrateur sont accessibles ici.
Le protocole SSL (Secure Socket Layer) a été développé par la société Netscape Communications Corporation pour permettre aux applications client/serveur de communiquer de façon sécurisée. TLS (Transport Layer Security) est une évolution de SSL réalisée par l’IETF.
SSL est un protocole qui s’intercale entre TCP/IP (OSI 3 et 4) et les applications (OSI 7) qui s’appuient sur TCP. Une session SSL se déroule en deux temps :
OpenSSL est une bibliothèque logicielle (boîte à outils) pour les applications, qui sécurise les communications sur les réseaux informatiques, en assurant :
openssl <commande> <options>
Des wrappers, permettant l'utilisation d’OpenSSL dans divers langages informatiques, sont également disponibles.
OpenSSL est disponible pour la plupart des systèmes d'exploitation de type Unix (y compris Linux, macOS et BSD) et Microsoft Windows.
OpenSSL a vu le jour en 1998. La version actuelle généralement utilisée est 1.1.1. Une version 3 sous licence Apache existe depuis septembre 2021 ; elle devrait apparaître dans les futures distributions d’OS.
Source : https://en.wikipedia.org/wiki/OpenSSL
Site officiel : https://www.openssl.org/
L’objet de ce TP est donc de découvrir les fonctions cryptographiques de base proposées par openSSL, au travers de la ligne de commande Linux.
Même si base64 n’est pas un système de chiffrement à proprement parler, il est utile pour sérialiser des données binaires quelconques en flux de caractères imprimables normalisé, ce qui est notamment utile pour la transmission de données binaires via des applications ou protocoles ne gérant que des données texte.
On va d'abord créer un fichier fic_bin
contenant 50 kilooctets de données binaires aléatoires :
dd if=/dev/urandom of=fic_bin bs=1k count=50
if=/dev/urandom
: utilise comme source d'entrée le générateur de nombres pseudo-aléatoires du systèmeof=fic_bin
: spécifie le fichier de sortiebs=1k
: définit la taille de bloc à 1 Kocount=50
: indique qu'on veut 50 blocs, ce qui donne un total de 50 KoPuis on encoder le fichier en base64
:
openssl base64 -e -in fic_bin -out fic_bin_b64
base64
: commande OpenSSL pour l'encodage/décodage base64-e
: spécifie l'encodage (peut être omis car c'est l'action par défaut)-in fic_bin
: fichier d'entrée à encoder-out fic_bin_b64
: fichier de sortie pour le résultat encodéVérifier que le fichier généré est bien un texte « pur » formaté selon le modèle particulier de base64 :
cat fic_bin_b64
Comparer la taille des fichiers ; base64 augmente en général la taille des fichiers de 1/3 ; constatez-vous cette proportion ?
ls -l fic_bin*
On décode le fichier base64 pour produire un nouveau fichier fic_bin2
:
openssl base64 -d -in fic_bin_b64 -out fic_bin2
Explication :
-d
: spécifie le décodage-in fic_bin_b64
: fichier encodé en entrée-out fic_bin2
: fichier de sortie pour les données binaires décodéesLes fichiers binaires sont-ils identiques ? vérifions :
diff -s fic_bin fic_bin2
Explication :
-s
: indique à diff
d'afficher un message si les fichiers sont identiquesOn va générer un autre fichier texte message aléatoire, selon une méthode différente :
cat /usr/share/dict/words | grep ker | tr "\n" " " > message
Explication : Crée un fichier texte contenant tous les mots du dictionnaire ayant ker comme sous-chaîne (vous pouvez bien entendu utiliser un autre filtre que ker)
grep ker
: filtre les lignes contenant "ker"tr "\n" " "
: remplace les sauts de ligne par des espacesmessage
: redirige le résultat vers un fichier nommé "message"cat message
On va chiffrer le message avec aes256 :
openssl enc -e -salt -in message -out message_c -aes256 -pbkdf2 -md sha256
Explication :
enc
: sous-commande pour le chiffrement/déchiffrement-e
: indique une opération de chiffrement-salt
: ajoute un sel aléatoire pour renforcer la sécurité (voir juste après)-in message
: fichier d'entrée non chiffré-out message_c
: fichier de sortie chiffré-aes256
: algorithme de chiffrement AES avec une clé de 256 bits-pbkdf2
: utilise l'algorithme PBKDF2 pour dériver la clé de chiffrement à partir du mot de passe-md sha256
: utilise SHA-256 comme fonction de hachage pour PBKDF2Avec l'option -salt
sur cette dernière commande, OpenSSL génère un sel aléatoire de 8 octets. Ce sel est utilisé avec le mot de passe pour calculer la clé de chiffrement effective et le vecteur d'initialisation (IV) via l'algorithme PBKDF2 qui lui-même va s'appuyer sur la fonction de hashage SHA-256 pour ses calculs. OpenSSL écrit ensuite au début du fichier chiffré :
Salted__
(8 octets) qui sert de marqueurAinsi, la structure du fichier de sortie message_c
ressemble à:
Salted__[8 octets de sel][données chiffrées]
Le sel, bien que lisible dans le fichier chiffré, renforce significativement la sécurité pour plusieurs raisons :
Le sel n'est pas supposé être secret. Sa fonction n'est pas d'être une information cachée comme la clé, mais plutôt d'être un élément aléatoire qui rend chaque opération de chiffrement unique.
L'intérêt principal de cette approche est qu'elle permet d'utiliser des mots de passe mémorisables par des humains, tout en générant des clés cryptographiques de haute qualité qui répondent aux exigences mathématiques des algorithmes comme AES.
Pour le déchiffrement, il faudra spécifier exactement les mêmes paramètres (-pbkdf2 -md sha256
), car ils déterminent comment la clé est dérivée à partir du mot de passe et du sel. Par contre, OpenSSL détectera automatiquement la présence de "sel" en lisant la chaîne magique "Salted__" dans le cryptogramme.
Enfin, SHA-256 est la fonction de hashage préférée, car elle offre plusieurs avantages :
On procède maintenant au déchiffrement :
openssl enc -d -in message_c -aes256 -pbkdf2 -md sha256
Explication :
-d
: indique une opération de déchiffrement-out
la sortie est donc sur l’écran (stdout) plutôt que dans un fichier.Le fichier clair (message) est un fichier texte, le cryptogramme obtenu (message_c
) est un fichier binaire, ce qui peut poser des problèmes dans certains contextes. Pour chiffrer et encoder en même temps en base64, ajouter l’option -a
(ou -base64
) aux commandes :
openssl enc -e -a -salt -in message -out message_c2 -aes256 -pbkdf2 -md sha256
cat message_c2
Pour avoir des infos sur les paramètres utilisés :
openssl enc -help
Et en savoir encore plus : https://www.openssl.org/
Générez une paire de clés RSA de 2048 bits (personnaliser le nom selon votre identifiant) :
openssl genrsa -out cle_pascal.pem 2048
Explication :
genrsa
: génère une paire de clés RSA-out cle_pascal.pem
: fichier de sortie pour la paire de clés2048
: taille de la clé en bits (plus le nombre est élevé, plus la sécurité est forte, mais aussi plus les opérations sont lentes)On préfèrera parfois l'algortithme
ED25519
àRSA
à cause de ses meilleures performances. La commande serait alorsopenssl genpkey -algorithm ED25519 -out cle_ed25519.pem
Regardons le contenu du fichier de la clé (qui est au format pem : privacy enhanced mail, donc encodée en base64) :
cat cle_pascal.pem
Repérer le format base64 reconnaissable et le balisage utilisé dans le fichier.
Visualiser les éléments constitutifs (paramètres) de la clé :
openssl rsa -in cle_pascal.pem -text -noout
Ce sont les paramètres mathématiques de la clé, exprimés en hexadécimal. On y trouve : le modulo, l’exposant public (quasiment toujours 216 + 1), l’exposant privé, deux nombres premiers prime1 et prime2, deux exposants associés 1 et 2, et un coefficient.
Pour en savoir plus : https://fr.wikipedia.org/wiki/Chiffrement_RSA
On protège notre paire de clés RSA, avec un chiffrement AES :
openssl rsa -in cle_pascal.pem -aes256 -out cle_pascal.pem
Explication :
-aes256
: chiffre la clé privée avec AES-256 pour la protéger par mot de passeVisualiser de nouveau la clé :
cat cle_pascal.pem
Le fichier chiffré demeure au format base64 avec des balises. Repérez les nouvelles informations ajoutées, et le nom exact de l’algorithme de chiffrement : AES-256-CBC (Cipher Block Chaining)
Nous allons exporter uniquement la clé publique (destinée donc à être publiée) :
openssl rsa -in cle_pascal.pem -pubout -out clepublique_pascal.pem
Voir la clé publique au format base64 :
cat clepublique_pascal.pem
Visualiser les paramètres de la clé publique :
openssl rsa -in clepublique_pascal.pem -pubin -text -noout
Explication :
-pubin
: indique que le fichier d'entrée contient une clé publique et non une clé privéeCréer un petit fichier contenant une passphrase de votre choix :
nano pass_pascal
Chiffrer ce fichier avec la clé publique :
openssl pkeyutl -encrypt -in pass_pascal -inkey clepublique_pascal.pem -pubin -out pass_pascal_c
Explication :
pkeyutl
: utilitaire pour les opérations cryptographiques de base avec des clés-encrypt
: chiffre le contenu du fichier d'entrée-in pass_pascal
: fichier contenant la donnée à chiffrer-inkey clepublique_pascal.pem
: clé publique utilisée pour le chiffrement-pubin
: indique que la clé d'entrée est une clé publique-out pass_pascal_c
: fichier de sortie pour les données chiffréesPour en savoir plus sur les paramètres utilisés :
openssl pkeyutl -help
Déchiffrement du fichier (forcément avec la clé privée...) :
openssl pkeyutl -decrypt -in pass_pascal_c -inkey cle_pascal.pem
Explication :
-decrypt
: déchiffre les données-inkey cle_pascal.pem
: utilise la clé privée correspondante pour le déchiffrementNous allons désormais utiliser openSSL pour deux cas de figure très classiques du chiffrement asymétrique : l’échange de clé secrète et la signature numérique.
/var/public
en y créant un sous-répertoire spécifique)message
)message_c
)secret
et message_c
)Pour réaliser une signature numérique avec OpenSSL, on utilise la commande openssl dgst
.
Créez un fichier texte appelé doc.txt
et insérez un message personnalisé (personnalisez aussi le nom du fichier).
Avec la commande suivante, vous allez générer une signature numérique (sceau) du document, c’est-à-dire une empreinte SHA256 du document, chiffrée avec votre clé privée :
openssl dgst -sha256 -sign cle_pascal.pem -out doc.txt.sha256 doc.txt
Explication :
dgst
: commande pour calculer les empreintes numériques (digest)-sha256
: utilise l'algorithme de hachage SHA-256-sign cle_pascal.pem
: signe le hachage avec la clé privée spécifiée-out doc.txt.sha256
: fichier de sortie pour la signaturedoc.txt
: document à signerPubliez (c’est-à-dire : "copiez dans le répertoire /var/public
") le document et la signature, et proposez à quelqu’un de vérifier que vous êtes l’auteur du document, en vérifiant la signature avec votre clé publique :
openssl dgst -sha256 -verify clepublique_pascal.pem -signature doc.txt.sha256 doc.txt
Explication :
-verify clepublique_pascal.pem
: spécifie la clé publique pour vérifier la signature-signature doc.txt.sha256
: fichier contenant la signature à vérifierSi le document est authentique, la vérification réussit.
Dans l’étape précédente, la signature est vérifiée, mais comment être sûr de l’authenticité de la clé publique ?
C’est la qu’intervient la notion de certificat, qui est une clé publique garantie par une autorité de certification (CA), en l’associant à d’autres informations concernant l’identité de l’entité.
Ici nous travaillerons avec une CA locale, c’est-à-dire une CA qui est reconnue uniquement sur le système Linux sur lequel nous travaillons.
Pour obtenir un certificat, il faut émettre un CSR. Cette demande est basée sur la clé de l’utilisateur :
openssl req -new -key pascal.pem -out pascal.csr
Explication :
req
: sous-commande pour gérer les requêtes PKCS#10
et les certificats X.509
-new
: crée une nouvelle requête de certificat-key pascal.pem
: spécifie la clé privée à utiliser-out pascal.csr
: fichier de sortie pour la demande de certificatDurant cette étape, vous devrez fournir plusieurs informations qui seront incluses dans le certificat :
Common Name (CN)
: généralement le nom complet (ex: "Alice Dupont")Organization (O)
: par exemple "Labo 6R"Il faut ensuite demander au formateur de récupérer votre CSR (en tant que root, il devrait accéder à votre dossier personnel)
Il va procéder à la signature de votre CSR avec le certificat de la CA, appelé certificat racine de confiance, et vous fournir en retour votre certificat, par exemple : pascal_cert.pem
.
Comment va-t-il procéder ?
De son côté, l’administrateur va lancer cette commande :
openssl x509 -req -in pascal.csr -CA ca-locale.crt -CAkey ca-key.pem -CAcreateserial -out pascal_cert.pem -days 90
Explications :
• x509
: sous-commande pour les certificats X.509
• -req
: indique que le fichier d'entrée est une demande de certificat
• -in pascal.csr
: fichier contenant la demande de certificat
• -CA ca-locale.crt
: certificat de l'autorité de certification
• -CAkey ca-key.pem
: clé privée de l'autorité de certification
• -CAcreateserial
: crée un fichier de numéro de série si nécessaire (le fichier .srl est créé dans le répertoire courant)
• -out pascal_cert.pem
: fichier de sortie pour le certificat signé
• -days 90
: durée de validité du certificat en jours
Pour obtenir les infos de votre certificat :
openssl x509 -in certificat.pem -noout -text
Explication :
-noout
: supprime l'affichage du certificat en format PEMVous créez un document texte, par exemple :
echo "Ceci est un message important de la part de Pascal." > exemple-pascal.txt
Puis vous générez une signature détachée pour ce fichier :
openssl dgst -sha256 -sign pascal.pem -out signature-pascal.bin exemple-pascal.txt
NB : il est important de comprendre que cette étape utilise votre la clé privée (pascal.pem) et non le certificat. Le certificat servira à un autre utilisateur pour vérifier la signature.
Pour vérifier l'authenticité, votre binôme a besoin de trois éléments :
exemple-pascal.txt
)signature-pascal.bin
)Pour extraire la clé publique du certificat :
openssl x509 -in pascal_cert.pem -pubkey -noout > pascal_pubkey.pem
Explication :
-pubkey
: extrait la clé publique du certificat-noout > pascal_pubkey.pem
: redirige la sortie vers un fichier sans afficher le format PEMVérification préalable que le certificat est bien signé par une CA du système :
openssl verify pascal_cert.pem
Explication :
verify
: vérifie que le certificat est bien signé par une autorité de confiance du systèmePuis pour vérifier ensuite l'authenticité du message :
openssl dgst -sha256 -verify pascal_pubkey.pem -signature signature-pascal.bin exemple-pascal.txt
Cette dernière commande vérifie que la signature correspond bien au document et qu'elle a été créée avec la clé privée associée à la clé publique extraite du certificat.
Nous avons fait un tour presque complet des fonctions offertes par openSSL. Il existe aussi, par exemple, tout un mécanisme pour révoquer des clés.
Nous reviendrons plus tard sur l’outil openSSL, notamment au travers d’un TP sur la mise en place de SSL/TLS sur un serveur WEB.