Services de sécurité et OpenSSL
Ce chapitre est consacré à l'étude des services de sécurité fondamentaux (confidentialité, intégrité, authentification, non-répudiation) et à leur mise en œuvre pratique à l'aide d'OpenSSL, la bibliothèque cryptographique la plus utilisée au monde.
3.1. Services de sécurité fondamentaux
La cryptographie moderne fournit quatre services de sécurité fondamentaux qui constituent les piliers de tout système de sécurité informatique :
Confidentialité
Objectif : Garantir que seules les parties autorisées peuvent accéder aux informations.
Mécanismes :
- Chiffrement symétrique (AES, ChaCha20)
- Chiffrement asymétrique (RSA, ECIES)
- Modes opératoires sécurisés (GCM, CTR)
Applications : Communications sécurisées, stockage de données sensibles, VPN, tunnels chiffrés
Intégrité
Objectif : Garantir que les données n'ont pas été modifiées de manière non autorisée.
Mécanismes :
- Fonctions de hachage (SHA-256, SHA-3, BLAKE2)
- Codes d'authentification de message (HMAC, KMAC)
- Chiffrement authentifié (GCM, ChaCha20-Poly1305)
Applications : Vérification d'intégrité des fichiers, protection contre la manipulation de données, chaînes de blocs
Authentification
Objectif : Vérifier l'identité d'une entité (utilisateur, système, application).
Mécanismes :
- Signatures numériques (RSA-PSS, ECDSA, EdDSA)
- Certificats numériques (X.509)
- Protocoles d'authentification (SASL, Kerberos)
- Authentification multifactorielle
Applications : Connexion sécurisée, signature électronique, authentification mutuelle TLS
Non-répudiation
Objectif : Empêcher une entité de nier avoir effectué une action ou envoyé un message.
Mécanismes :
- Signatures numériques avec certificats
- Horodatage sécurisé
- Autorités de certification
- Journalisation sécurisée
Applications : Contrats électroniques, systèmes de vote, transactions financières, preuves légales
Relations entre les services de sécurité
Ces quatre services sont interdépendants et se complètent mutuellement :
Combinaison | Résultat | Exemple de mise en œuvre |
---|---|---|
Confidentialité + Intégrité | Protection complète des données contre la lecture et la modification non autorisées | Chiffrement authentifié (AES-GCM, ChaCha20-Poly1305) |
Intégrité + Authentification | Garantie de l'origine et de l'intégrité des données | Signatures numériques (RSA, ECDSA) |
Authentification + Non-répudiation | Identification prouvable et indéniable | Signatures avec certificats et horodatage |
Tous les services | Sécurité complète de bout en bout | TLS 1.3 avec authentification mutuelle et chiffrement authentifié |
3.2. Introduction à OpenSSL
Qu'est-ce qu'OpenSSL ?
OpenSSL est une boîte à outils cryptographique complète qui offre :
- Une bibliothèque d'implémentations d'algorithmes cryptographiques (
libcrypto
) - Une implémentation des protocoles SSL/TLS (
libssl
) - Un outil en ligne de commande pour diverses opérations cryptographiques
Développé depuis 1998, OpenSSL est devenu la référence en matière de cryptographie sur les systèmes Unix/Linux et est largement utilisé sur de nombreuses plateformes. Plus de 70% des serveurs web dans le monde reposent sur OpenSSL pour leurs communications sécurisées.
Composants principaux
- libcrypto : Implémentations de base des algorithmes
- Chiffrement symétrique et asymétrique
- Fonctions de hachage
- Génération de nombres aléatoires cryptographiques
- Codes d'authentification de message
- libssl : Implémentation des protocoles SSL/TLS
- Établissement de sessions sécurisées
- Gestion des certificats
- Négociation des algorithmes
- Outil en ligne de commande : Interface utilisateur pour les opérations cryptographiques
Historique et versions importantes
Création d'OpenSSL
Basé sur SSLeay (développé par Eric A. Young et Tim J. Hudson)
Vulnérabilité Heartbleed (CVE-2014-0160)
Faille critique permettant de lire la mémoire d'un serveur. A conduit à une refonte majeure des pratiques de développement.
OpenSSL 1.1.0
Refonte majeure de l'API, amélioration de la sécurité et des performances
Support de TLS 1.3
Implémentation de la version la plus récente et la plus sécurisée du protocole TLS
OpenSSL 3.0
Architecture modulaire, nouveau "provider" API, support amélioré pour les algorithmes post-quantiques
Premiers pas avec l'outil en ligne de commande
L'outil en ligne de commande OpenSSL est organisé en sous-commandes spécialisées :
# Afficher la version d'OpenSSL
openssl version -a
# Lister les sous-commandes disponibles
openssl help
# Lister les algorithmes de chiffrement supportés
openssl list -cipher-algorithms
# Lister les fonctions de hachage supportées
openssl list -digest-algorithms
# Générer un nombre aléatoire cryptographique (16 octets)
openssl rand -hex 16
3.3. Implémentation de la confidentialité avec OpenSSL
Chiffrement de fichiers
OpenSSL permet de chiffrer et déchiffrer facilement des fichiers avec différents algorithmes et modes opératoires :
Chiffrement symétrique avec AES-256-GCM
# Générer une clé AES-256 aléatoire et la stocker dans un fichier
openssl rand -out key.bin 32
# Générer un IV/nonce aléatoire
openssl rand -out iv.bin 12
# Chiffrer un fichier avec AES-256-GCM
openssl enc -aes-256-gcm -in plaintext.txt -out encrypted.bin \
-K $(xxd -p -c 64 key.bin) \
-iv $(xxd -p -c 24 iv.bin) \
-tag tag.bin
# Déchiffrer le fichier
openssl enc -d -aes-256-gcm -in encrypted.bin -out decrypted.txt \
-K $(xxd -p -c 64 key.bin) \
-iv $(xxd -p -c 24 iv.bin) \
-tag tag.bin
Chiffrement symétrique avec mot de passe
# Chiffrer un fichier avec un mot de passe (utilise PBKDF2 pour dériver la clé)
openssl enc -aes-256-cbc -salt -pbkdf2 \
-in plaintext.txt -out encrypted.bin
# Déchiffrer le fichier
openssl enc -d -aes-256-cbc -salt -pbkdf2 \
-in encrypted.bin -out decrypted.txt
Chiffrement asymétrique avec RSA
# Générer une paire de clés RSA
openssl genpkey -algorithm RSA -out private_key.pem -pkeyopt rsa_keygen_bits:2048
openssl pkey -in private_key.pem -pubout -out public_key.pem
# Chiffrer avec la clé publique (noter la limite de taille)
openssl pkeyutl -encrypt -pubin -inkey public_key.pem \
-in small_plaintext.txt -out encrypted.bin
# Déchiffrer avec la clé privée
openssl pkeyutl -decrypt -inkey private_key.pem \
-in encrypted.bin -out decrypted.txt
Chiffrement de grande quantité de données
Pour chiffrer de grandes quantités de données avec RSA, on utilise généralement une approche hybride :
- Générer une clé symétrique aléatoire (clé de session)
- Chiffrer les données avec cette clé symétrique
- Chiffrer la clé symétrique avec la clé publique RSA
- Transmettre le message chiffré et la clé de session chiffrée
Implémentation d'un chiffrement hybride avec OpenSSL
#!/bin/bash
# Ce script illustre le chiffrement hybride
# Fichier à chiffrer
input_file="fichier_large.dat"
output_file="fichier_large.enc"
# Générer une paire de clés RSA (si nécessaire)
if [ ! -f recipient_public.pem ]; then
echo "Génération d'une paire de clés RSA..."
openssl genpkey -algorithm RSA -out recipient_private.pem -pkeyopt rsa_keygen_bits:2048
openssl pkey -in recipient_private.pem -pubout -out recipient_public.pem
fi
# 1. Générer une clé AES-256 aléatoire
echo "Génération d'une clé AES-256 aléatoire..."
openssl rand -out session_key.bin 32
# 2. Générer un IV aléatoire pour AES-GCM
echo "Génération d'un IV aléatoire..."
openssl rand -out iv.bin 12
# 3. Chiffrer le fichier avec AES-256-GCM
echo "Chiffrement du fichier avec AES-256-GCM..."
openssl enc -aes-256-gcm -in "$input_file" -out "$output_file" \
-K $(xxd -p -c 64 session_key.bin) \
-iv $(xxd -p -c 24 iv.bin) \
-tag tag.bin
# 4. Chiffrer la clé de session avec la clé publique RSA
echo "Chiffrement de la clé de session avec RSA..."
openssl pkeyutl -encrypt -pubin -inkey recipient_public.pem \
-in session_key.bin -out encrypted_key.bin
# 5. Combiner tous les éléments dans un seul fichier
# Format: [Taille de la clé chiffrée (4 octets)][Clé chiffrée][IV][Tag][Données chiffrées]
key_size=$(stat -c%s encrypted_key.bin)
iv_size=$(stat -c%s iv.bin)
tag_size=$(stat -c%s tag.bin)
echo "Assemblage du fichier final..."
# Écrire la taille de la clé chiffrée (format little-endian)
printf "\\x$(printf "%08x" $key_size | grep -o ..$)" | xxd -r > "$output_file.final"
# Concaténer tous les éléments
cat encrypted_key.bin iv.bin tag.bin "$output_file" >> "$output_file.final"
echo "Fichier chiffré créé: $output_file.final"
echo "Taille de la clé chiffrée: $key_size octets"
echo "Taille de l'IV: $iv_size octets"
echo "Taille du tag: $tag_size octets"
# Script de déchiffrement (démonstration)
cat > decrypt.sh << 'EOL'
#!/bin/bash
# Script de déchiffrement
input_file="$1"
output_file="$2"
private_key="$3"
if [ $# -ne 3 ]; then
echo "Usage: $0 fichier_chiffre fichier_sortie cle_privee.pem"
exit 1
fi
# Lire la taille de la clé chiffrée (4 premiers octets)
key_size=$(od -An -t u4 -N 4 "$input_file" | tr -d ' ')
# Extraire la clé chiffrée
dd if="$input_file" of="encrypted_key.bin" bs=1 skip=4 count="$key_size" 2>/dev/null
# Extraire l'IV (12 octets pour GCM)
dd if="$input_file" of="iv.bin" bs=1 skip=$((4 + key_size)) count=12 2>/dev/null
# Extraire le tag d'authentification (16 octets pour GCM)
dd if="$input_file" of="tag.bin" bs=1 skip=$((4 + key_size + 12)) count=16 2>/dev/null
# Extraire les données chiffrées
dd if="$input_file" of="data.enc" bs=1 skip=$((4 + key_size + 12 + 16)) 2>/dev/null
# Déchiffrer la clé de session
openssl pkeyutl -decrypt -inkey "$private_key" \
-in encrypted_key.bin -out session_key.bin
# Déchiffrer les données
openssl enc -d -aes-256-gcm -in data.enc -out "$output_file" \
-K $(xxd -p -c 64 session_key.bin) \
-iv $(xxd -p -c 24 iv.bin) \
-tag tag.bin
# Nettoyage
rm -f encrypted_key.bin iv.bin tag.bin data.enc session_key.bin
echo "Déchiffrement terminé: $output_file"
EOL
chmod +x decrypt.sh
echo "Script de déchiffrement créé: decrypt.sh"
Recommandations pratiques pour la confidentialité
- Toujours utiliser des modes opératoires sécurisés (GCM, ChaCha20-Poly1305) qui fournissent à la fois confidentialité et intégrité
- Générer des clés et des IV aléatoires en utilisant
openssl rand
(jamais de constantes ou de valeurs prévisibles) - Protéger les clés privées avec des permissions de fichier restrictives et des phrases de passe fortes
- Éviter l'utilisation de CBC sans protection HMAC additionnelle (vulnérable aux attaques par padding oracle)
- Utiliser des algorithmes standardisés et bien audités : AES-256, ChaCha20 pour le chiffrement symétrique
- Pour RSA, utiliser au minimum 2048 bits et toujours avec un padding sécurisé (OAEP)
3.4. Implémentation de l'intégrité et de l'authentification
Calcul et vérification de hachés
OpenSSL permet de générer facilement des valeurs de hachage pour vérifier l'intégrité des fichiers :
# Calculer un hash SHA-256
openssl dgst -sha256 fichier.txt
# Calculer un hash SHA-3-256
openssl dgst -sha3-256 fichier.txt
# Calculer un hash avec sortie binaire
openssl dgst -sha256 -binary fichier.txt > fichier.sha256
# Calculer un hash avec sortie hexadécimale dans un fichier
openssl dgst -sha256 -hex fichier.txt > fichier.sha256.hex
Génération et vérification de HMAC
HMAC (Hash-based Message Authentication Code) combine une clé secrète avec une fonction de hachage pour authentifier un message :
# Générer une clé secrète
openssl rand -out hmac_key.bin 32
# Calculer un HMAC-SHA256
openssl dgst -sha256 -hmac $(xxd -p -c 64 hmac_key.bin) fichier.txt
# Sauvegarder le HMAC dans un fichier
openssl dgst -sha256 -hmac $(xxd -p -c 64 hmac_key.bin) -binary fichier.txt > fichier.hmac
# Vérifier le HMAC
calculated_hmac=$(openssl dgst -sha256 -hmac $(xxd -p -c 64 hmac_key.bin) -binary fichier.txt | xxd -p)
stored_hmac=$(xxd -p fichier.hmac)
if [ "$calculated_hmac" = "$stored_hmac" ]; then
echo "HMAC vérifié - Intégrité confirmée"
else
echo "HMAC incorrect - Données modifiées"
fi
Signatures numériques
Les signatures numériques permettent à la fois d'assurer l'intégrité des données et d'authentifier leur source :
Génération et vérification de signatures RSA
# Générer une paire de clés RSA
openssl genpkey -algorithm RSA -out private_key.pem -pkeyopt rsa_keygen_bits:2048
openssl pkey -in private_key.pem -pubout -out public_key.pem
# Signer un fichier avec RSA-SHA256
openssl dgst -sha256 -sign private_key.pem -out signature.bin fichier.txt
# Vérifier la signature
openssl dgst -sha256 -verify public_key.pem -signature signature.bin fichier.txt
Génération et vérification de signatures ECDSA
# Générer une paire de clés sur la courbe P-256
openssl genpkey -algorithm EC -out ec_private.pem -pkeyopt ec_paramgen_curve:P-256
openssl pkey -in ec_private.pem -pubout -out ec_public.pem
# Signer un fichier avec ECDSA-SHA256
openssl dgst -sha256 -sign ec_private.pem -out ec_signature.bin fichier.txt
# Vérifier la signature ECDSA
openssl dgst -sha256 -verify ec_public.pem -signature ec_signature.bin fichier.txt
Génération de signature
- Calculer le haché du message : \(h = H(m)\)
- Chiffrer le haché avec la clé privée : \(s = Sign_{sk}(h)\)
- La signature est \(s\)
Vérification de signature
- Calculer le haché du message reçu : \(h' = H(m')\)
- Déchiffrer la signature avec la clé publique : \(h'' = Verify_{pk}(s)\)
- Comparer \(h'\) et \(h''\) : si égaux, la signature est valide
Schémas de signature recommandés
Algorithme | Caractéristiques | Taille de clé recommandée | Taille de signature | Avantages/Inconvénients |
---|---|---|---|---|
RSA-PSS | Basé sur RSA avec Probabilistic Signature Scheme | 3072 bits ou plus | 384 octets (RSA-3072) | Largement supporté mais signatures volumineuses |
ECDSA | Basé sur les courbes elliptiques | P-256 (256 bits) | 64 octets (P-256) | Signatures compactes, clés petites, mais sensible à la génération d'aléa |
Ed25519 | Signature EdDSA sur courbe Edwards | 256 bits | 64 octets | Hautement sécurisé, performant, signatures déterministes, mais support moins universel |
Utilisation d'Ed25519 avec OpenSSL
# Générer une paire de clés Ed25519
openssl genpkey -algorithm ED25519 -out ed25519_private.pem
openssl pkey -in ed25519_private.pem -pubout -out ed25519_public.pem
# Signer un fichier avec Ed25519
openssl pkeyutl -sign -inkey ed25519_private.pem -in fichier.txt -out ed25519_sig.bin
# Vérifier la signature Ed25519
openssl pkeyutl -verify -pubin -inkey ed25519_public.pem -in fichier.txt -sigfile ed25519_sig.bin
Recommandations pratiques pour l'intégrité et l'authentification
- Préférer les fonctions de hachage modernes : SHA-256, SHA3-256, BLAKE2
- Toujours utiliser une clé secrète avec les hachés (HMAC) quand l'authentification est nécessaire
- Pour les signatures, privilégier Ed25519 quand le support est disponible
- Pour RSA, utiliser PSS plutôt que PKCS#1 v1.5
- Vérifier soigneusement les erreurs lors de la validation des signatures
- Inclure des métadonnées (identifiant de l'émetteur, horodatage) dans le message signé pour éviter les attaques par rejeu
3.5. Mise en œuvre de services complets avec OpenSSL
Protection complète d'un fichier
Voici comment combiner confidentialité, intégrité et authentification pour protéger complètement un fichier :
#!/bin/bash
# secure_file.sh - Protection complète d'un fichier
if [ $# -ne 3 ]; then
echo "Usage: $0 input_file output_file recipient_public_key.pem"
exit 1
fi
input_file="$1"
output_file="$2"
recipient_pub="$3"
# Générer une clé de signature si elle n'existe pas
if [ ! -f signing_key.pem ]; then
echo "Génération d'une clé de signature Ed25519..."
openssl genpkey -algorithm ED25519 -out signing_key.pem
openssl pkey -in signing_key.pem -pubout -out signing_key.pub
echo "Clé publique de signature générée: signing_key.pub"
echo "IMPORTANT: Distribuez cette clé publique aux destinataires pour la vérification"
fi
# 1. Signer le fichier original
echo "Signature du fichier original..."
openssl pkeyutl -sign -inkey signing_key.pem -rawin -in "$input_file" > "$input_file.sig"
# 2. Générer une clé AES-256 aléatoire pour le chiffrement
echo "Génération d'une clé de chiffrement AES-256..."
openssl rand -out session_key.bin 32
# 3. Générer un nonce aléatoire pour ChaCha20-Poly1305
echo "Génération d'un nonce aléatoire..."
openssl rand -out nonce.bin 12
# 4. Chiffrer le fichier avec ChaCha20-Poly1305
echo "Chiffrement du fichier avec ChaCha20-Poly1305..."
openssl enc -chacha20-poly1305 -in "$input_file" -out "$input_file.enc" \
-K $(xxd -p -c 64 session_key.bin) \
-iv $(xxd -p -c 24 nonce.bin) \
-tag tag.bin
# 5. Chiffrer la clé de session avec la clé publique RSA du destinataire
echo "Chiffrement de la clé de session..."
openssl pkeyutl -encrypt -pubin -inkey "$recipient_pub" \
-in session_key.bin -out encrypted_key.bin \
-pkeyopt rsa_padding_mode:oaep \
-pkeyopt rsa_oaep_md:sha256
# 6. Créer un fichier de métadonnées
cat > metadata.json << EOL
{
"format": "secure_file_v1",
"encryption": "chacha20-poly1305",
"key_encryption": "rsa-oaep-sha256",
"signature": "ed25519",
"timestamp": "$(date -u +%Y-%m-%dT%H:%M:%SZ)",
"sender": "$(whoami)@$(hostname)"
}
EOL
# 7. Combiner tous les éléments dans un seul fichier
echo "Création du fichier sécurisé final..."
# Créer une structure simple pour stocker tous les éléments
(
# Écrire les tailles de chaque composant (4 octets chacun)
python3 -c "import struct; print(struct.pack(' "$output_file"
# 8. Nettoyer les fichiers temporaires
rm -f metadata.json encrypted_key.bin nonce.bin tag.bin "$input_file.sig" "$input_file.enc" session_key.bin
echo "Fichier sécurisé créé: $output_file"
# 9. Créer un script de déchiffrement
cat > unsecure_file.sh << 'EOL'
#!/bin/bash
# Script de déchiffrement et de vérification
if [ $# -ne 4 ]; then
echo "Usage: $0 input_file output_file private_key.pem signer_public_key.pem"
exit 1
fi
input_file="$1"
output_file="$2"
private_key="$3"
signer_pubkey="$4"
# Extraire les tailles des composants
read -r metadata_size encrypted_key_size nonce_size tag_size sig_size data_size < <(
python3 -c "
import struct
with open('$input_file', 'rb') as f:
sizes = [struct.unpack('/dev/null
offset=$((offset + metadata_size))
# Extraire la clé chiffrée
dd if="$input_file" of="encrypted_key.bin" bs=1 skip=$offset count=$encrypted_key_size 2>/dev/null
offset=$((offset + encrypted_key_size))
# Extraire le nonce
dd if="$input_file" of="nonce.bin" bs=1 skip=$offset count=$nonce_size 2>/dev/null
offset=$((offset + nonce_size))
# Extraire le tag
dd if="$input_file" of="tag.bin" bs=1 skip=$offset count=$tag_size 2>/dev/null
offset=$((offset + tag_size))
# Extraire la signature
dd if="$input_file" of="signature.bin" bs=1 skip=$offset count=$sig_size 2>/dev/null
offset=$((offset + sig_size))
# Extraire les données chiffrées
dd if="$input_file" of="data.enc" bs=1 skip=$offset count=$data_size 2>/dev/null
# Déchiffrer la clé de session
echo "Déchiffrement de la clé de session..."
openssl pkeyutl -decrypt -inkey "$private_key" \
-in encrypted_key.bin -out session_key.bin \
-pkeyopt rsa_padding_mode:oaep \
-pkeyopt rsa_oaep_md:sha256
# Déchiffrer les données
echo "Déchiffrement des données..."
openssl enc -d -chacha20-poly1305 -in data.enc -out "$output_file" \
-K $(xxd -p -c 64 session_key.bin) \
-iv $(xxd -p -c 24 nonce.bin) \
-tag tag.bin
# Vérifier la signature
echo "Vérification de la signature..."
if openssl pkeyutl -verify -pubin -inkey "$signer_pubkey" \
-rawin -in "$output_file" -sigfile signature.bin; then
echo "Signature vérifiée - Authenticité confirmée"
else
echo "AVERTISSEMENT: Signature invalide - Le fichier pourrait avoir été modifié ou provenir d'une autre source!"
fi
# Afficher les métadonnées
echo "Métadonnées du fichier:"
cat metadata.json
# Nettoyage
rm -f metadata.json encrypted_key.bin nonce.bin tag.bin signature.bin data.enc session_key.bin
echo "Déchiffrement terminé: $output_file"
EOL
chmod +x unsecure_file.sh
echo "Script de déchiffrement créé: unsecure_file.sh"
Services de sécurité dans les applications
Dans les applications réelles, ces services de sécurité sont souvent imbriqués et s'appuient les uns sur les autres :
Chiffrement de disque
Services : Principalement confidentialité, parfois intégrité
Mécanismes :
- Mode XTS pour le chiffrement par secteur
- Dérivation de clé basée sur mot de passe (PBKDF2, Argon2)
- En-têtes authentifiés
Exemples : LUKS, BitLocker, FileVault
Messagerie sécurisée
Services : Confidentialité, intégrité, authentification, parfois non-répudiation
Mécanismes :
- Chiffrement de bout en bout
- Chiffrement hybride (curve25519 + AES-GCM)
- Signatures pour l'authentification
- Perfect Forward Secrecy (PFS)
Exemples : Signal Protocol, PGP, Matrix
Communications Web
Services : Confidentialité, intégrité, authentification
Mécanismes :
- TLS pour le tunnel sécurisé
- Certificats X.509 pour l'authentification
- AEAD pour le chiffrement authentifié
- HKDF pour la dérivation de clés
Exemples : HTTPS, WSS (WebSockets sécurisés)
Bonnes pratiques de sécurité pour les développeurs
- Ne jamais réinventer la roue : Utiliser des bibliothèques cryptographiques éprouvées comme OpenSSL
- Mettre à jour régulièrement les bibliothèques cryptographiques pour corriger les vulnérabilités
- Générer correctement l'aléa cryptographique avec
openssl rand
ou équivalent - Vérifier rigoureusement toutes les entrées et sorties des opérations cryptographiques
- Utiliser des combinaisons validées d'algorithmes et de modes (cipher suites)
- Suivre des guides de bonnes pratiques comme ceux de OWASP ou du NIST
- Prévoir des mécanismes de rotation des clés et de révocation des certificats
- Protéger les clés privées avec des HSM (Hardware Security Modules) quand cela est possible
Exercices associés
Mettez en pratique les concepts de ce chapitre avec les travaux pratiques dédiés.
Accéder aux exercices