Plateforme de Cryptographie Par Kaci AMAOUCHE

Travaux Pratiques - PKI et certificats numériques

Mise en œuvre et analyse des infrastructures à clés publiques


TP 1: Création d'une PKI complète avec OpenSSL

Objectifs
  • Mettre en place une hiérarchie de confiance à deux niveaux
  • Créer et gérer des certificats pour différents usages
  • Comprendre le cycle de vie complet des certificats

Partie 1: Préparation de l'environnement

Nous allons commencer par créer la structure de répertoires et les fichiers de configuration nécessaires pour notre PKI :

#!/bin/bash
# setup_pki.sh - Script de préparation de l'environnement PKI

# Créer l'arborescence
mkdir -p pki/{root-ca,inter-ca}/{private,certs,crl,csr,newcerts,db}

# Définir les permissions appropriées
chmod 700 pki/{root-ca,inter-ca}/private

# Créer les fichiers de base de données
touch pki/root-ca/db/index
echo 1000 > pki/root-ca/db/serial
echo 1000 > pki/root-ca/db/crlnumber

touch pki/inter-ca/db/index
echo 1000 > pki/inter-ca/db/serial
echo 1000 > pki/inter-ca/db/crlnumber

# Créer le fichier de configuration pour la CA racine
cat > pki/root-ca/root-ca.conf << 'EOT'
# Configuration de la CA racine

[ ca ]
default_ca = CA_default

[ CA_default ]
dir               = pki/root-ca
certs             = $dir/certs
crl_dir           = $dir/crl
new_certs_dir     = $dir/newcerts
database          = $dir/db/index
serial            = $dir/db/serial
RANDFILE          = $dir/private/.rand
private_key       = $dir/private/root-ca.key
certificate       = $dir/certs/root-ca.crt
crlnumber         = $dir/db/crlnumber
crl               = $dir/crl/root-ca.crl
crl_extensions    = crl_ext
default_crl_days  = 30
default_md        = sha256
name_opt          = ca_default
cert_opt          = ca_default
default_days      = 3650
preserve          = no
policy            = policy_strict

[ policy_strict ]
# Les CA doivent avoir les mêmes informations que la CA racine
countryName             = match
stateOrProvinceName     = match
organizationName        = match
organizationalUnitName  = optional
commonName              = supplied
emailAddress            = optional

[ policy_loose ]
# Pour les certificats d'entités finales
countryName             = optional
stateOrProvinceName     = optional
localityName            = optional
organizationName        = optional
organizationalUnitName  = optional
commonName              = supplied
emailAddress            = optional

[ req ]
default_bits        = 4096
distinguished_name  = req_distinguished_name
string_mask         = utf8only
default_md          = sha256
x509_extensions     = v3_ca

[ req_distinguished_name ]
countryName                     = Pays (code à deux lettres)
stateOrProvinceName             = Région
localityName                    = Ville
0.organizationName              = Organisation
organizationalUnitName          = Service
commonName                      = Nom commun
emailAddress                    = Adresse email

countryName_default             = FR
stateOrProvinceName_default     = Ile-de-France
localityName_default            = Paris
0.organizationName_default      = MonOrganisation
organizationalUnitName_default  = PKI Lab
commonName_default              = MonOrganisation Root CA
emailAddress_default            = ca@monorganisation.fr

[ v3_ca ]
# Extensions pour une CA
subjectKeyIdentifier = hash
authorityKeyIdentifier = keyid:always,issuer
basicConstraints = critical, CA:true
keyUsage = critical, digitalSignature, cRLSign, keyCertSign

[ v3_intermediate_ca ]
# Extensions pour une CA intermédiaire
subjectKeyIdentifier = hash
authorityKeyIdentifier = keyid:always,issuer
basicConstraints = critical, CA:true, pathlen:0
keyUsage = critical, digitalSignature, cRLSign, keyCertSign

[ usr_cert ]
# Extensions pour les certificats client
basicConstraints = CA:FALSE
nsCertType = client, email
nsComment = "Certificat client OpenSSL"
subjectKeyIdentifier = hash
authorityKeyIdentifier = keyid,issuer
keyUsage = critical, nonRepudiation, digitalSignature, keyEncipherment
extendedKeyUsage = clientAuth, emailProtection

[ server_cert ]
# Extensions pour les certificats serveur
basicConstraints = CA:FALSE
nsCertType = server
nsComment = "Certificat serveur OpenSSL"
subjectKeyIdentifier = hash
authorityKeyIdentifier = keyid,issuer:always
keyUsage = critical, digitalSignature, keyEncipherment
extendedKeyUsage = serverAuth

[ crl_ext ]
# Extensions pour les CRLs
authorityKeyIdentifier=keyid:always

[ ocsp ]
# Extensions pour le certificat OCSP responder
basicConstraints = CA:FALSE
subjectKeyIdentifier = hash
authorityKeyIdentifier = keyid,issuer
keyUsage = critical, digitalSignature
extendedKeyUsage = critical, OCSPSigning
EOT

# Créer le fichier de configuration pour la CA intermédiaire (basé sur celui de la CA racine)
sed 's/root-ca/inter-ca/g; s/policy_strict/policy_loose/g; s/v3_ca/v3_intermediate_ca/g; s/MonOrganisation Root CA/MonOrganisation Intermediate CA/g' pki/root-ca/root-ca.conf > pki/inter-ca/inter-ca.conf

echo "Structure PKI initialisée avec succès!"
echo "Arborescence :"
find pki -type d | sort

Partie 2: Création de la CA racine

Dans cette partie, nous allons créer l'autorité de certification racine, qui représente l'ancre de confiance de notre PKI :

#!/bin/bash
# create_root_ca.sh - Création de la CA racine

cd pki  # Travailler dans le répertoire de la PKI

# Générer la clé privée pour la CA racine (protégée par passphrase)
openssl genrsa -aes256 -out root-ca/private/root-ca.key 4096

# Définir les permissions appropriées
chmod 400 root-ca/private/root-ca.key

# Créer le certificat auto-signé de la CA racine
openssl req -config root-ca/root-ca.conf -key root-ca/private/root-ca.key \
    -new -x509 -days 7300 -sha256 -extensions v3_ca \
    -out root-ca/certs/root-ca.crt

# Vérifier le certificat
openssl x509 -noout -text -in root-ca/certs/root-ca.crt

# Générer la liste de révocation initiale (CRL)
openssl ca -config root-ca/root-ca.conf -gencrl -out root-ca/crl/root-ca.crl

echo "CA racine créée avec succès!"
echo "Empreinte du certificat racine:"
openssl x509 -noout -fingerprint -sha256 -in root-ca/certs/root-ca.crt

Partie 3: Création de la CA intermédiaire

Maintenant, nous allons créer une CA intermédiaire signée par notre CA racine :

#!/bin/bash
# create_intermediate_ca.sh - Création de la CA intermédiaire

cd pki  # Travailler dans le répertoire de la PKI

# Générer la clé privée pour la CA intermédiaire
openssl genrsa -aes256 -out inter-ca/private/inter-ca.key 4096

# Définir les permissions appropriées
chmod 400 inter-ca/private/inter-ca.key

# Créer une demande de signature de certificat (CSR)
openssl req -config inter-ca/inter-ca.conf -new -sha256 \
    -key inter-ca/private/inter-ca.key \
    -out inter-ca/csr/inter-ca.csr

# Signer la CSR avec la CA racine
openssl ca -config root-ca/root-ca.conf -extensions v3_intermediate_ca \
    -days 3650 -notext -md sha256 \
    -in inter-ca/csr/inter-ca.csr \
    -out inter-ca/certs/inter-ca.crt

# Vérifier le certificat intermédiaire
openssl x509 -noout -text -in inter-ca/certs/inter-ca.crt

# Vérifier la chaîne de certification
openssl verify -CAfile root-ca/certs/root-ca.crt inter-ca/certs/inter-ca.crt

# Générer la liste de révocation initiale
openssl ca -config inter-ca/inter-ca.conf -gencrl -out inter-ca/crl/inter-ca.crl

# Créer le bundle de la chaîne de certification
cat inter-ca/certs/inter-ca.crt root-ca/certs/root-ca.crt > inter-ca/certs/ca-chain.crt

echo "CA intermédiaire créée avec succès!"
echo "Chaîne de certification créée: inter-ca/certs/ca-chain.crt"

Partie 4: Émission de certificats d'entité finale

Nous allons maintenant émettre différents types de certificats pour des entités finales :

#!/bin/bash
# issue_certificates.sh - Émission de certificats d'entité finale

cd pki  # Travailler dans le répertoire de la PKI

# Fonction pour créer un certificat serveur
create_server_cert() {
    local name=$1
    local cn=$2
    
    echo "Création du certificat serveur pour $name ($cn)..."
    
    # Créer la clé privée
    openssl genrsa -out inter-ca/private/${name}.key 2048
    chmod 400 inter-ca/private/${name}.key
    
    # Créer la CSR
    openssl req -config inter-ca/inter-ca.conf \
        -key inter-ca/private/${name}.key \
        -new -sha256 -out inter-ca/csr/${name}.csr \
        -subj "/C=FR/ST=Ile-de-France/L=Paris/O=MonOrganisation/OU=Serveurs/CN=${cn}"
    
    # Signer la CSR pour créer le certificat serveur
    openssl ca -config inter-ca/inter-ca.conf \
        -extensions server_cert -days 375 -notext -md sha256 \
        -in inter-ca/csr/${name}.csr \
        -out inter-ca/certs/${name}.crt
    
    # Vérifier le certificat
    openssl verify -CAfile inter-ca/certs/ca-chain.crt inter-ca/certs/${name}.crt
    
    # Créer un bundle serveur (clé + certificat)
    cat inter-ca/certs/${name}.crt inter-ca/private/${name}.key > inter-ca/certs/${name}.pem
    chmod 400 inter-ca/certs/${name}.pem
    
    echo "Certificat serveur pour $name créé avec succès!"
}

# Fonction pour créer un certificat client
create_client_cert() {
    local name=$1
    local cn=$2
    local email=$3
    
    echo "Création du certificat client pour $name ($cn)..."
    
    # Créer la clé privée
    openssl genrsa -out inter-ca/private/${name}.key 2048
    chmod 400 inter-ca/private/${name}.key
    
    # Créer la CSR
    openssl req -config inter-ca/inter-ca.conf \
        -key inter-ca/private/${name}.key \
        -new -sha256 -out inter-ca/csr/${name}.csr \
        -subj "/C=FR/ST=Ile-de-France/L=Paris/O=MonOrganisation/OU=Utilisateurs/CN=${cn}/emailAddress=${email}"
    
    # Signer la CSR pour créer le certificat client
    openssl ca -config inter-ca/inter-ca.conf \
        -extensions usr_cert -days 375 -notext -md sha256 \
        -in inter-ca/csr/${name}.csr \
        -out inter-ca/certs/${name}.crt
    
    # Vérifier le certificat
    openssl verify -CAfile inter-ca/certs/ca-chain.crt inter-ca/certs/${name}.crt
    
    # Créer un fichier PKCS#12 pour l'importation dans les navigateurs
    openssl pkcs12 -export -out inter-ca/certs/${name}.p12 \
        -inkey inter-ca/private/${name}.key \
        -in inter-ca/certs/${name}.crt \
        -certfile inter-ca/certs/ca-chain.crt \
        -passout pass:changeit
    
    echo "Certificat client pour $name créé avec succès!"
    echo "Fichier PKCS#12 créé: inter-ca/certs/${name}.p12 (mot de passe: changeit)"
}

# Créer des certificats serveur
create_server_cert "www-server" "www.monorganisation.fr"
create_server_cert "mail-server" "mail.monorganisation.fr"

# Créer des certificats client
create_client_cert "alice" "Alice Dupont" "alice@monorganisation.fr"
create_client_cert "bob" "Bob Martin" "bob@monorganisation.fr"

echo "Tous les certificats ont été créés avec succès !"

Partie 5: Démonstration de révocation

Enfin, nous allons voir comment révoquer un certificat et vérifier son statut :

#!/bin/bash
# demonstrate_revocation.sh - Révocation d'un certificat

cd pki  # Travailler dans le répertoire de la PKI

# Révoquer le certificat d'Alice (compromission simulée)
echo "Révocation du certificat d'Alice..."
openssl ca -config inter-ca/inter-ca.conf \
    -revoke inter-ca/certs/alice.crt \
    -crl_reason keyCompromise

# Générer une nouvelle CRL
echo "Génération de la nouvelle CRL..."
openssl ca -config inter-ca/inter-ca.conf \
    -gencrl -out inter-ca/crl/inter-ca.crl

# Vérifier la CRL
echo "Détails de la CRL mise à jour:"
openssl crl -in inter-ca/crl/inter-ca.crl -noout -text

# Vérifier le statut de révocation d'un certificat
echo -e "\nVérification du statut des certificats:"
echo "Alice (révoqué):"
openssl verify -CAfile inter-ca/certs/ca-chain.crt -crl_check \
    -CRLfile inter-ca/crl/inter-ca.crl inter-ca/certs/alice.crt || echo "Certificat révoqué"

echo -e "\nBob (valide):"
openssl verify -CAfile inter-ca/certs/ca-chain.crt -crl_check \
    -CRLfile inter-ca/crl/inter-ca.crl inter-ca/certs/bob.crt

echo "Démonstration de révocation terminée!"

Partie 6: Questions d'analyse

  1. Pourquoi est-il recommandé d'utiliser une CA intermédiaire pour l'émission des certificats d'entité finale plutôt que d'utiliser directement la CA racine ?
  2. Analysez les extensions X.509v3 dans les différents types de certificats (racine, intermédiaire, serveur, client). Comment ces extensions influencent-elles l'utilisation des certificats ?
  3. Quelles précautions supplémentaires devriez-vous prendre dans un environnement de production par rapport à ce TP pour protéger les clés privées des CAs ?
  4. Comment vérifieriez-vous qu'un certificat révoqué n'est plus accepté par un service qui utilise cette PKI ?
  5. Dans notre PKI de test, la durée de validité de la CA racine est de 20 ans et celle de la CA intermédiaire de 10 ans. Quels sont les avantages et les inconvénients de ces longues durées de validité ?

TP 2: Analyse et manipulation de certificats

Objectifs
  • Analyser en détail la structure des certificats X.509
  • Manipuler les certificats dans différents formats d'encodage
  • Comprendre les mécanismes de validation des certificats

Partie 1: Extraction et analyse de certificats TLS

Commençons par extraire et analyser des certificats de sites web populaires :

#!/bin/bash
# extract_certificates.sh - Extraction et analyse de certificats de sites web

# Créer un répertoire pour les certificats
mkdir -p cert_analysis

# Fonction pour extraire et analyser un certificat
analyze_cert() {
    local domain=$1
    local output_dir="cert_analysis/${domain}"
    mkdir -p "$output_dir"
    
    echo "Extraction du certificat de $domain..."
    
    # Extraire le certificat avec OpenSSL
    echo | openssl s_client -showcerts -servername $domain -connect $domain:443 2>/dev/null \
        | awk '/BEGIN CERTIFICATE/,/END CERTIFICATE/ {print}' > "$output_dir/cert.pem"
    
    # Extraire la chaîne complète de certificats
    echo | openssl s_client -showcerts -servername $domain -connect $domain:443 2>/dev/null \
        | awk '/BEGIN CERTIFICATE/,/END CERTIFICATE/ {print}' > "$output_dir/chain.pem"
    
    # Analyser le certificat
    echo "Analyse du certificat de $domain..."
    
    # Informations générales
    openssl x509 -in "$output_dir/cert.pem" -noout -text > "$output_dir/cert_details.txt"
    
    # Extraire des informations spécifiques
    echo "Émetteur:" > "$output_dir/summary.txt"
    openssl x509 -in "$output_dir/cert.pem" -noout -issuer >> "$output_dir/summary.txt"
    echo -e "\nSujet:" >> "$output_dir/summary.txt"
    openssl x509 -in "$output_dir/cert.pem" -noout -subject >> "$output_dir/summary.txt"
    echo -e "\nDates de validité:" >> "$output_dir/summary.txt"
    openssl x509 -in "$output_dir/cert.pem" -noout -dates >> "$output_dir/summary.txt"
    echo -e "\nEmpreinte SHA-256:" >> "$output_dir/summary.txt"
    openssl x509 -in "$output_dir/cert.pem" -noout -fingerprint -sha256 >> "$output_dir/summary.txt"
    echo -e "\nNoms alternatifs du sujet (SAN):" >> "$output_dir/summary.txt"
    openssl x509 -in "$output_dir/cert.pem" -noout -ext subjectAltName >> "$output_dir/summary.txt"
    
    # Vérifier si le certificat utilise Certificate Transparency
    echo -e "\nCertificate Transparency:" >> "$output_dir/summary.txt"
    if openssl x509 -in "$output_dir/cert.pem" -noout -ext 1.3.6.1.4.1.11129.2.4.2 2>/dev/null >> "$output_dir/summary.txt"; then
        echo "  SCT présents" >> "$output_dir/summary.txt"
    else
        echo "  Pas de SCT détectés" >> "$output_dir/summary.txt"
    fi
    
    # Convertir en format DER
    openssl x509 -in "$output_dir/cert.pem" -outform DER -out "$output_dir/cert.der"
    
    echo "Analyse de $domain terminée."
}

# Analyser différents types de sites
analyze_cert "www.google.com"
analyze_cert "www.github.com"
analyze_cert "www.example.com"

echo "Extraction et analyse terminées. Résultats dans le répertoire cert_analysis/"

Partie 2: Comparaison et conversion des formats de certificats

Dans cette partie, nous allons explorer les différents formats de certificats et leur interconversion :

#!/bin/bash
# certificate_formats.sh - Manipulation des formats de certificats

# Créer un répertoire pour les tests de format
mkdir -p cert_formats

# Utiliser un certificat de l'exercice précédent
cp cert_analysis/www.google.com/cert.pem cert_formats/original.pem
cd cert_formats

echo "Démonstration des différents formats de certificats..."

# Format PEM (base64 avec headers) - déjà présent comme original.pem
echo "1. Format PEM - Lisible en texte avec des délimiteurs BEGIN/END"
head -3 original.pem
echo "..."
tail -3 original.pem
echo ""

# Format DER (binaire)
echo "2. Conversion PEM vers DER (binaire)"
openssl x509 -in original.pem -outform DER -out certificate.der
echo "Taille du fichier DER: $(stat -c%s certificate.der) octets"
echo "Aperçu hexadécimal du DER:"
hexdump -C certificate.der | head -3
echo "..."
echo ""

# Format PKCS#7 (.p7b, .p7c) - peut contenir des chaînes de certificats
echo "3. Conversion PEM vers PKCS#7"
openssl crl2pkcs7 -nocrl -certfile original.pem -out certificate.p7b
echo "Contenu du PKCS#7:"
openssl pkcs7 -in certificate.p7b -print_certs -noout
echo ""

# Récupérer le PEM à partir du PKCS#7
echo "4. Récupération PEM à partir de PKCS#7"
openssl pkcs7 -in certificate.p7b -print_certs -out from_p7b.pem
diff -s original.pem from_p7b.pem
echo ""

# Format PKCS#12 (.p12, .pfx) - contient certificats et clés privées
echo "5. Création d'un fichier PKCS#12 (nécessite une clé privée)"
# Générer une clé privée pour la démonstration
openssl genrsa -out private.key 2048
# Créer un PKCS#12
openssl pkcs12 -export -out certificate.p12 -inkey private.key -in original.pem -passout pass:changeit
echo "PKCS#12 créé avec mot de passe: changeit"
echo "Contenu du PKCS#12:"
openssl pkcs12 -in certificate.p12 -info -noout -passin pass:changeit | head -10
echo "..."
echo ""

# Récupérer le certificat et la clé du PKCS#12
echo "6. Extraction à partir du PKCS#12"
openssl pkcs12 -in certificate.p12 -clcerts -nokeys -out cert_from_p12.pem -passin pass:changeit
openssl pkcs12 -in certificate.p12 -nocerts -out key_from_p12.pem -passin pass:changeit -passout pass:changeit
echo "Certificat et clé extraits du PKCS#12"
echo ""

# Afficher les empreintes pour vérifier l'équivalence
echo "7. Vérification de l'équivalence des certificats dans différents formats"
echo "Empreinte de l'original (PEM):"
openssl x509 -in original.pem -noout -fingerprint -sha256
echo "Empreinte après conversion DER→PEM:"
openssl x509 -in certificate.der -inform DER -noout -fingerprint -sha256
echo "Empreinte après PKCS#7→PEM:"
openssl x509 -in from_p7b.pem -noout -fingerprint -sha256
echo "Empreinte après PKCS#12→PEM:"
openssl x509 -in cert_from_p12.pem -noout -fingerprint -sha256

echo "Démonstration des formats de certificats terminée!"

Partie 3: Vérification des chaînes de certification

Nous allons maintenant explorer la validation des chaînes de certificats et la vérification des chemins de certification :

#!/bin/bash
# verify_certificates.sh - Vérification des chaînes de certification

# Créer un répertoire pour les tests de validation
mkdir -p cert_validation
cd cert_validation

echo "Démonstration de la validation des chaînes de certificats..."

# Télécharger un certificat et sa chaîne
echo "1. Extraction de la chaîne complète pour github.com"
echo | openssl s_client -showcerts -connect github.com:443 2>/dev/null > github_full.pem

# Extraire les certificats individuels de la chaîne
echo "2. Extraction des certificats individuels de la chaîne"
awk 'BEGIN {c=0} /BEGIN CERT/{c++} { print > "cert" c ".pem"}' < github_full.pem
echo "Certificats extraits: cert1.pem (entité finale), cert2.pem (intermédiaire), etc."

# Vérifier la chaîne avec les certificats racines du système
echo "3. Vérification avec les certificats racines du système"
openssl verify cert1.pem
echo ""

# Vérifier manuellement la chaîne
echo "4. Construction et vérification manuelle de la chaîne"
cat cert2.pem cert3.pem > chain.pem
openssl verify -CAfile chain.pem cert1.pem
echo ""

# Explorer les détails du certificat intermédiaire
echo "5. Analyse du certificat intermédiaire"
openssl x509 -in cert2.pem -noout -text | grep -E "Issuer:|Subject:|CA:"
echo ""

# Vérifier la signature du certificat d'entité finale avec la clé publique de l'émetteur
echo "6. Vérification de la signature du certificat d'entité finale"
# Extraire la clé publique de l'émetteur
openssl x509 -in cert2.pem -pubkey -noout > issuer_pubkey.pem
# Extraire la signature du certificat d'entité finale
openssl x509 -in cert1.pem -text -noout | grep -A 100 Signature | tail -n +2 > signature.hex
# Cette vérification est simplifiée; en pratique, la vérification de signature est plus complexe
echo "Clé publique de l'émetteur et signature extraites"
echo ""

# Vérifier le statut de révocation (OCSP)
echo "7. Vérification OCSP (si disponible)"
OCSP_URI=$(openssl x509 -in cert1.pem -noout -ocsp_uri 2>/dev/null)
if [ -n "$OCSP_URI" ]; then
    echo "URI OCSP trouvée: $OCSP_URI"
    
    # Extraire le certificat de l'émetteur
    ISSUER_CERT="cert2.pem"
    
    # Effectuer la requête OCSP
    echo "Envoi d'une requête OCSP..."
    openssl ocsp -issuer $ISSUER_CERT -cert cert1.pem -url $OCSP_URI -resp_text
else
    echo "Pas d'URI OCSP trouvée dans le certificat"
fi

echo "Démonstration de validation des chaînes terminée!"

Partie 4: Création et vérification de signatures avec des certificats

Dans cette partie, nous allons utiliser des certificats pour signer et vérifier des données :

#!/bin/bash
# certificate_signatures.sh - Démonstration de signatures avec certificats

# Créer un répertoire pour les tests de signature
mkdir -p cert_signatures
cd cert_signatures

echo "Démonstration de l'utilisation de certificats pour les signatures..."

# Créer un fichier à signer
echo "Message important qui nécessite une signature pour prouver son authenticité." > document.txt

# 1. Générer une paire de clés et un certificat auto-signé
echo "1. Création d'un certificat pour la signature"
openssl req -x509 -newkey rsa:2048 -keyout private.key -out certificate.pem -days 365 -nodes \
    -subj "/C=FR/ST=Ile-de-France/L=Paris/O=Demo Corp/OU=PKI Demo/CN=Signature Demo"

# Afficher les détails du certificat
echo "Détails du certificat généré:"
openssl x509 -in certificate.pem -noout -text | grep -E "Issuer:|Subject:|Key Usage:"
echo ""

# 2. Signer le document avec la clé privée
echo "2. Signature du document"
openssl dgst -sha256 -sign private.key -out document.sig document.txt
echo "Signature créée: document.sig"
echo ""

# 3. Extraire la clé publique du certificat
echo "3. Extraction de la clé publique du certificat"
openssl x509 -in certificate.pem -pubkey -noout > pubkey.pem
echo "Clé publique extraite: pubkey.pem"
echo ""

# 4. Vérifier la signature avec la clé publique
echo "4. Vérification de la signature avec la clé publique"
if openssl dgst -sha256 -verify pubkey.pem -signature document.sig document.txt; then
    echo "Signature valide: l'intégrité et l'authenticité du document sont confirmées."
else
    echo "Signature invalide: le document pourrait avoir été modifié ou la signature est incorrecte."
fi
echo ""

# 5. Démontrer l'échec de vérification en cas de modification
echo "5. Test de détection de modification"
# Créer une copie modifiée du document
cat document.txt > modified_document.txt
echo " Cette ligne a été ajoutée après la signature." >> modified_document.txt

echo "Vérification de la signature avec le document modifié:"
if openssl dgst -sha256 -verify pubkey.pem -signature document.sig modified_document.txt; then
    echo "Signature valide (inattendu)."
else
    echo "Signature invalide: modification détectée comme prévu."
fi
echo ""

# 6. Créer une signature PKCS#7 avec le certificat inclus
echo "6. Création d'une signature PKCS#7 (incluant le certificat)"
openssl smime -sign -in document.txt -out document.p7s -signer certificate.pem \
    -inkey private.key -outform DER

echo "Signature PKCS#7 créée: document.p7s"
echo "Informations sur la signature PKCS#7:"
openssl pkcs7 -in document.p7s -inform DER -print_certs -noout
echo ""

# 7. Vérifier la signature PKCS#7
echo "7. Vérification de la signature PKCS#7"
openssl smime -verify -in document.p7s -inform DER -content document.txt

echo "Démonstration de signatures avec certificats terminée!"

Partie 5: Questions d'analyse

  1. Comparez les chaînes de certificats des différents sites web analysés en Partie 1. Quelles différences observez-vous en termes de longueur de chaîne, d'autorités de certification et d'extensions utilisées ?
  2. Pourquoi les certificats sont-ils souvent distribués dans le format PEM plutôt que DER, alors que le format DER est plus compact ?
  3. D'après vos observations, quelle est la différence fondamentale entre les formats PKCS#7 et PKCS#12 ? Dans quels contextes chacun est-il utilisé ?
  4. Expliquez le processus de validation d'une chaîne de certificats. Quelles vérifications sont effectuées à chaque étape et pourquoi sont-elles importantes ?
  5. Comment la vérification OCSP diffère-t-elle de la vérification par CRL ? Quels sont les avantages et inconvénients de chaque approche ?

TP 3: Mise en œuvre d'une authentification mutuelle TLS

Objectifs
  • Configurer un serveur web avec authentification client TLS
  • Préparer des certificats pour les clients et le serveur
  • Tester et analyser le mécanisme d'authentification mutuelle

Partie 1: Configuration de l'environnement

Nous allons mettre en place un environnement complet pour tester l'authentification mutuelle TLS :

#!/bin/bash
# setup_mtls_environment.sh - Préparation de l'environnement mTLS

# Créer un répertoire pour l'exercice
mkdir -p mtls_demo/{ca,server,clients}
cd mtls_demo

echo "Configuration de l'environnement pour l'authentification mutuelle TLS..."

# 1. Créer une autorité de certification pour le test
echo "1. Création d'une CA pour les tests"
openssl req -x509 -newkey rsa:2048 -days 365 -nodes \
  -keyout ca/ca.key -out ca/ca.crt \
  -subj "/C=FR/ST=Ile-de-France/L=Paris/O=MTLS Demo/OU=CA/CN=MTLS Demo CA"

# 2. Créer un certificat pour le serveur
echo "2. Création du certificat serveur"
# Générer la clé serveur
openssl genrsa -out server/server.key 2048

# Créer la CSR avec les SAN appropriés
cat > server/server.cnf << 'EOT'
[req]
default_bits = 2048
prompt = no
default_md = sha256
req_extensions = req_ext
distinguished_name = dn

[dn]
C=FR
ST=Ile-de-France
L=Paris
O=MTLS Demo
OU=Servers
CN=localhost

[req_ext]
subjectAltName = @alt_names

[alt_names]
DNS.1 = localhost
IP.1 = 127.0.0.1
EOT

openssl req -new -key server/server.key -out server/server.csr -config server/server.cnf

# Signer la CSR du serveur
openssl x509 -req -in server/server.csr -CA ca/ca.crt -CAkey ca/ca.key -CAcreateserial \
  -out server/server.crt -days 365 -extensions req_ext -extfile server/server.cnf

# 3. Créer des certificats pour les clients
echo "3. Création des certificats clients"

create_client_cert() {
    local client_name=$1
    
    echo "  Génération du certificat pour $client_name..."
    
    # Générer la clé client
    openssl genrsa -out clients/${client_name}.key 2048
    
    # Créer la CSR
    openssl req -new -key clients/${client_name}.key -out clients/${client_name}.csr \
      -subj "/C=FR/ST=Ile-de-France/L=Paris/O=MTLS Demo/OU=Clients/CN=${client_name}"
    
    # Signer la CSR client
    openssl x509 -req -in clients/${client_name}.csr -CA ca/ca.crt -CAkey ca/ca.key -CAcreateserial \
      -out clients/${client_name}.crt -days 365
    
    # Créer un fichier PKCS#12 pour l'importation dans les navigateurs
    openssl pkcs12 -export -out clients/${client_name}.p12 -inkey clients/${client_name}.key \
      -in clients/${client_name}.crt -certfile ca/ca.crt -passout pass:changeit
    
    echo "  Certificat pour $client_name créé (PKCS#12 password: changeit)"
}

create_client_cert "alice"
create_client_cert "bob"
create_client_cert "eve"  # Utilisateur non autorisé

# 4. Créer une liste de révocation (CRL)
echo "4. Création d'une CRL et révocation du certificat d'Eve"

# Configurer OpenSSL pour la gestion de la CRL
cat > ca/ca.cnf << 'EOT'
[ ca ]
default_ca = CA_default

[ CA_default ]
database = ca/index.txt
crlnumber = ca/crlnumber
default_md = sha256
EOT

# Initialiser la base de données de certificats
touch ca/index.txt
echo "01" > ca/crlnumber

# Ajouter les certificats à la base de données
openssl x509 -in server/server.crt -noout -serial -subject | sed 's/serial=//' | sed 's/subject= //' > ca/temp
echo "V\t$(date -u -d '+365 days' +'%y%m%d%H%M%SZ')\t\t$(cat ca/temp)" >> ca/index.txt

openssl x509 -in clients/alice.crt -noout -serial -subject | sed 's/serial=//' | sed 's/subject= //' > ca/temp
echo "V\t$(date -u -d '+365 days' +'%y%m%d%H%M%SZ')\t\t$(cat ca/temp)" >> ca/index.txt

openssl x509 -in clients/bob.crt -noout -serial -subject | sed 's/serial=//' | sed 's/subject= //' > ca/temp
echo "V\t$(date -u -d '+365 days' +'%y%m%d%H%M%SZ')\t\t$(cat ca/temp)" >> ca/index.txt

openssl x509 -in clients/eve.crt -noout -serial -subject | sed 's/serial=//' | sed 's/subject= //' > ca/temp
echo "V\t$(date -u -d '+365 days' +'%y%m%d%H%M%SZ')\t\t$(cat ca/temp)" >> ca/index.txt

# Révoquer le certificat d'Eve
openssl ca -config ca/ca.cnf -cert ca/ca.crt -keyfile ca/ca.key \
  -revoke clients/eve.crt -crl_reason keyCompromise

# Générer la CRL
openssl ca -config ca/ca.cnf -cert ca/ca.crt -keyfile ca/ca.key \
  -gencrl -out ca/ca.crl

rm ca/temp

echo "5. Configuration du serveur web"

# Créer un répertoire pour le serveur web
mkdir -p server/www
echo "Bienvenue sur le serveur sécurisé mTLS!" > server/www/index.html
echo "Si vous voyez cette page, votre certificat client a été accepté." >> server/www/index.html

# Créer un fichier de configuration pour nginx
cat > server/nginx.conf << 'EOT'
worker_processes 1;
error_log stderr;
pid /tmp/nginx.pid;

events {
    worker_connections 1024;
}

http {
    include /etc/nginx/mime.types;
    default_type application/octet-stream;
    
    # Définir un serveur HTTP simple pour rediriger vers HTTPS
    server {
        listen 8080;
        server_name localhost;
        
        location / {
            return 301 https://$host:8443$request_uri;
        }
    }
    
    # Serveur principal avec mTLS
    server {
        listen 8443 ssl;
        server_name localhost;
        
        # Certificats serveur
        ssl_certificate /etc/nginx/ssl/server.crt;
        ssl_certificate_key /etc/nginx/ssl/server.key;
        
        # Configuration client TLS
        ssl_client_certificate /etc/nginx/ssl/ca.crt;
        ssl_verify_client on;
        ssl_verify_depth 1;
        
        # Configuration optimale TLS
        ssl_protocols TLSv1.2 TLSv1.3;
        ssl_prefer_server_ciphers on;
        ssl_ciphers 'ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384';
        
        # Vérification CRL (si disponible)
        ssl_crl /etc/nginx/ssl/ca.crl;
        
        # Racine du site
        root /var/www/html;
        index index.html;
        
        # Afficher des informations sur le client
        location / {
            add_header X-Client-DN $ssl_client_s_dn;
            add_header X-Client-Verify $ssl_client_verify;
            add_header X-Client-Serial $ssl_client_serial;
        }
        
        # Endpoint pour afficher les détails du certificat client
        location /clientinfo {
            default_type text/plain;
            return 200 "
Client DN: $ssl_client_s_dn
Client I DN: $ssl_client_i_dn
Client Verify: $ssl_client_verify
Client Serial: $ssl_client_serial
Client Fingerprint: $ssl_client_fingerprint
";
        }
    }
}
EOT

# Créer un script pour lancer le serveur nginx dans Docker
cat > run_server.sh << 'EOT'
#!/bin/bash
docker run --rm -it \
  -p 8080:8080 -p 8443:8443 \
  -v $(pwd)/server/www:/var/www/html \
  -v $(pwd)/server/nginx.conf:/etc/nginx/nginx.conf \
  -v $(pwd)/server:/etc/nginx/ssl \
  -v $(pwd)/ca/ca.crt:/etc/nginx/ssl/ca.crt \
  -v $(pwd)/ca/ca.crl:/etc/nginx/ssl/ca.crl \
  nginx:latest
EOT
chmod +x run_server.sh

# Créer un script pour tester avec curl
cat > test_client.sh << 'EOT'
#!/bin/bash

if [ $# -lt 1 ]; then
    echo "Usage: $0 client_name"
    exit 1
fi

CLIENT_NAME=$1
echo "Test d'accès avec le certificat de $CLIENT_NAME..."

# Test avec certificat client
echo "Test avec authentification client:"
curl --insecure \
  --cert clients/${CLIENT_NAME}.crt \
  --key clients/${CLIENT_NAME}.key \
  https://localhost:8443/clientinfo

echo -e "\nTentative sans certificat client:"
curl --insecure https://localhost:8443/

EOT
chmod +x test_client.sh

echo "Environnement mTLS configuré avec succès!"
echo "Pour démarrer le serveur, exécutez: ./run_server.sh"
echo "Pour tester avec un client, exécutez: ./test_client.sh alice"

Partie 2: Analyse du handshake TLS mutuel

Examinons en détail comment fonctionne le handshake TLS avec authentification mutuelle :

#!/bin/bash
# analyze_mtls_handshake.sh - Analyse du handshake TLS mutuel

cd mtls_demo

echo "Analyse du handshake TLS avec authentification mutuelle..."

# Créer un répertoire pour les captures
mkdir -p captures

# 1. Capture du handshake TLS standard (sans authentification client)
echo "1. Capture d'un handshake TLS standard (sans mTLS)"
openssl s_client -connect www.google.com:443 -servername www.google.com \
  -showcerts -msg -state -debug > captures/normal_handshake.txt 2>&1  captures/server_log.txt 2>&1 &
SERVER_PID=$!

# Attendre que le serveur démarre
sleep 1

# Se connecter avec le certificat client
openssl s_client -connect localhost:44330 -cert clients/alice.crt -key clients/alice.key \
  -CAfile ca/ca.crt -showcerts -msg -state -debug > captures/mtls_handshake.txt 2>&1  captures/handshake_comparison.txt
grep -A 1 "<<< TLS" captures/normal_handshake.txt | grep -v "^\-\-\-" >> captures/handshake_comparison.txt
grep -A 1 ">>> TLS" captures/normal_handshake.txt | grep -v "^\-\-\-" >> captures/handshake_comparison.txt

echo -e "\nMessages du handshake mTLS:" >> captures/handshake_comparison.txt
grep -A 1 "<<< TLS" captures/mtls_handshake.txt | grep -v "^\-\-\-" >> captures/handshake_comparison.txt
grep -A 1 ">>> TLS" captures/mtls_handshake.txt | grep -v "^\-\-\-" >> captures/handshake_comparison.txt

echo "Comparaison des handshakes enregistrée dans captures/handshake_comparison.txt"

# 4. Visualiser le handshake mTLS
cat > captures/mtls_handshake_diagram.txt << 'EOT'
Client                                                           Serveur
  |                                                                 |
  |  ClientHello                                                    |
  |  + extensions (supported_groups, signature_algorithms, etc.)    |
  | ----------------------------------------------------------------> |
  |                                                                 |
  |                                           ServerHello           |
  |                            + extensions (key_share, etc.)       |
  |                                    Certificate                  |
  |                          (certificat serveur + chaîne)          |
  |                                CertificateRequest               |
  |                           (demande certificat client)           |
  |                                ServerKeyExchange                |
  |                                ServerHelloDone                  |
  | <---------------------------------------------------------------- |
  |                                                                 |
  |  Certificate                                                    |
  |  (certificat client + chaîne)                                   |
  |  ClientKeyExchange                                              |
  |  CertificateVerify                                              |
  |  (signature avec la clé privée du client)                       |
  |  ChangeCipherSpec                                               |
  |  Finished                                                       |
  | ----------------------------------------------------------------> |
  |                                                                 |
  |                                    ChangeCipherSpec             |
  |                                    Finished                     |
  | <---------------------------------------------------------------- |
  |                                                                 |
  |  Application Data                                               |
  | <--------------------------------------------------------------> |
  |                                                                 |
EOT

echo "Diagramme du handshake mTLS généré dans captures/mtls_handshake_diagram.txt"

# 5. Analyse du certificat client envoyé
echo "5. Analyse du certificat client envoyé pendant le handshake"
grep -A 30 "Certificate chain" captures/mtls_handshake.txt > captures/client_cert_in_handshake.txt

echo "Analyse du handshake TLS mutuel terminée!"

Partie 3: Implémentation en Python d'un client et serveur mTLS

Pour mieux comprendre l'authentification mutuelle TLS, nous allons créer un simple client et serveur en Python :

#!/usr/bin/env python3
# mtls_server.py - Serveur simple avec authentification mutuelle TLS

import socket
import ssl
import threading
import datetime
import argparse

def handle_client(conn, addr, client_cert):
    """Gérer une connexion client."""
    try:
        # Extraire les informations du certificat client
        cert_subject = client_cert.get('subject')
        cert_issuer = client_cert.get('issuer')
        cert_serial = client_cert.get('serialNumber')
        cert_not_after = client_cert.get('notAfter')
        
        print(f"[+] Connexion sécurisée avec {addr}")
        print(f"    Subject: {cert_subject}")
        print(f"    Issuer: {cert_issuer}")
        print(f"    Serial: {cert_serial}")
        print(f"    Valide jusqu'au: {cert_not_after}")
        
        # Envoyer un message au client
        current_time = datetime.datetime.now().strftime("%Y-%m-%d %H:%M:%S")
        response = f"Bonjour {cert_subject}!\r\n"
        response += f"Vous êtes connecté via mTLS à {current_time}\r\n"
        response += f"Votre certificat a été émis par {cert_issuer}\r\n"
        
        conn.sendall(response.encode())
        
        # Recevoir les données du client
        data = conn.recv(1024)
        if data:
            print(f"[+] Message reçu: {data.decode().strip()}")
            conn.sendall(b"Message recu. Au revoir!\r\n")
        
    except Exception as e:
        print(f"[-] Erreur lors de la gestion du client: {e}")
    finally:
        conn.close()

def start_server(host, port, certfile, keyfile, cafile):
    """Démarrer le serveur TLS avec authentification mutuelle."""
    # Créer le contexte SSL avec authentification client requise
    context = ssl.create_default_context(ssl.Purpose.CLIENT_AUTH)
    context.verify_mode = ssl.CERT_REQUIRED
    context.load_cert_chain(certfile=certfile, keyfile=keyfile)
    context.load_verify_locations(cafile=cafile)
    
    # Configuration des versions de TLS et des ciphersuites
    context.options |= ssl.OP_NO_TLSv1 | ssl.OP_NO_TLSv1_1  # Désactiver TLS 1.0 et 1.1
    context.set_ciphers('ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384')
    
    # Créer le socket serveur
    with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as server:
        server.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
        server.bind((host, port))
        server.listen(5)
        print(f"[*] Serveur mTLS démarré sur {host}:{port}")
        print(f"[*] Utilise le certificat: {certfile}")
        print(f"[*] CA de confiance: {cafile}")
        print(f"[*] Authentification client requise")
        
        try:
            while True:
                # Accepter les connexions
                client, addr = server.accept()
                
                # Envelopper la connexion dans TLS
                try:
                    ssl_client = context.wrap_socket(client, server_side=True)
                    
                    # Obtenir le certificat client
                    client_cert = ssl_client.getpeercert()
                    
                    # Gérer le client dans un thread séparé
                    client_thread = threading.Thread(
                        target=handle_client,
                        args=(ssl_client, addr, client_cert)
                    )
                    client_thread.daemon = True
                    client_thread.start()
                    
                except ssl.SSLError as e:
                    print(f"[-] Erreur SSL avec {addr}: {e}")
                    client.close()
                    
        except KeyboardInterrupt:
            print("\n[*] Arrêt du serveur")
            
if __name__ == "__main__":
    parser = argparse.ArgumentParser(description="Simple mTLS Server")
    parser.add_argument("--host", default="localhost", help="Adresse d'écoute")
    parser.add_argument("--port", type=int, default=4433, help="Port d'écoute")
    parser.add_argument("--cert", required=True, help="Certificat serveur")
    parser.add_argument("--key", required=True, help="Clé privée serveur")
    parser.add_argument("--ca", required=True, help="Certificat CA pour vérifier les clients")
    
    args = parser.parse_args()
    
    start_server(args.host, args.port, args.cert, args.key, args.ca)
#!/usr/bin/env python3
# mtls_client.py - Client simple avec authentification mutuelle TLS

import socket
import ssl
import argparse

def connect_to_server(host, port, certfile, keyfile, cafile):
    """Se connecter à un serveur avec authentification mutuelle TLS."""
    # Créer le contexte SSL
    context = ssl.create_default_context(ssl.Purpose.SERVER_AUTH)
    context.load_cert_chain(certfile=certfile, keyfile=keyfile)
    context.load_verify_locations(cafile=cafile)
    
    # Configuration des versions de TLS
    context.options |= ssl.OP_NO_TLSv1 | ssl.OP_NO_TLSv1_1  # Désactiver TLS 1.0 et 1.1
    
    # Créer le socket client
    with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as client:
        # Envelopper dans TLS
        with context.wrap_socket(client, server_hostname=host) as tls_client:
            try:
                print(f"[*] Connexion à {host}:{port}")
                tls_client.connect((host, port))
                
                # Afficher les informations TLS
                cipher = tls_client.cipher()
                print(f"[+] Connexion établie")
                print(f"    Version: {tls_client.version()}")
                print(f"    Chiffrement: {cipher[0]}")
                print(f"    Bits: {cipher[2]}")
                
                # Certificat serveur
                server_cert = tls_client.getpeercert()
                print(f"[+] Certificat serveur:")
                print(f"    Sujet: {server_cert['subject']}")
                print(f"    Émetteur: {server_cert['issuer']}")
                
                # Envoyer une requête
                tls_client.sendall(b"Hello from mTLS client\r\n")
                
                # Recevoir la réponse
                response = b""
                while True:
                    data = tls_client.recv(1024)
                    if not data:
                        break
                    response += data
                
                print(f"\n[+] Réponse du serveur:")
                print(response.decode())
                
            except ssl.SSLError as e:
                print(f"[-] Erreur SSL: {e}")
            except Exception as e:
                print(f"[-] Erreur: {e}")

if __name__ == "__main__":
    parser = argparse.ArgumentParser(description="Simple mTLS Client")
    parser.add_argument("--host", default="localhost", help="Adresse du serveur")
    parser.add_argument("--port", type=int, default=4433, help="Port du serveur")
    parser.add_argument("--cert", required=True, help="Certificat client")
    parser.add_argument("--key", required=True, help="Clé privée client")
    parser.add_argument("--ca", required=True, help="Certificat CA pour vérifier le serveur")
    
    args = parser.parse_args()
    
    connect_to_server(args.host, args.port, args.cert, args.key, args.ca)

Pour exécuter et tester ces scripts, utilisez les commandes suivantes :

# Dans un terminal, démarrer le serveur
cd mtls_demo
python3 mtls_server.py --cert server/server.crt --key server/server.key --ca ca/ca.crt

# Dans un autre terminal, exécuter le client avec le certificat d'Alice
python3 mtls_client.py --cert clients/alice.crt --key clients/alice.key --ca ca/ca.crt

# Essayer avec le certificat de Bob
python3 mtls_client.py --cert clients/bob.crt --key clients/bob.key --ca ca/ca.crt

# Essayer avec le certificat d'Eve (révoqué, devrait échouer si CRL est correctement configurée)
python3 mtls_client.py --cert clients/eve.crt --key clients/eve.key --ca ca/ca.crt

Partie 4: Questions d'analyse

  1. Comment le serveur peut-il distinguer entre les différents clients dans une configuration mTLS ? Quelles informations peut-il utiliser pour prendre des décisions d'autorisation ?
  2. Analysez les différences entre un handshake TLS standard et un handshake TLS mutuel. Quels messages supplémentaires sont échangés et à quelles fins ?
  3. Dans quels contextes l'authentification mutuelle TLS est-elle préférable à d'autres méthodes d'authentification (comme l'authentification par mot de passe ou par jeton) ?
  4. Quels sont les défis opérationnels liés au déploiement et à la gestion d'une solution mTLS à grande échelle ? Comment pourriez-vous les atténuer ?
  5. Comment les navigateurs web gèrent-ils la sélection du certificat client lors d'une connexion mTLS ? Quelles sont les implications pour l'expérience utilisateur ?

TP 4: Projet pratique - Système de signature de documents

Objectifs
  • Concevoir et implémenter un système complet de signature de documents basé sur PKI
  • Mettre en pratique les concepts de certificats, de validation et de révocation
  • Créer une application réelle qui pourrait être utilisée dans un contexte professionnel

Dans ce projet, vous allez développer un système de signature numérique de documents exploitant les certificats X.509 et l'infrastructure à clés publiques. Ce système permettra de :

  • Signer numériquement des documents PDF ou textuels
  • Vérifier l'authenticité et l'intégrité des documents signés
  • Gérer les certificats et les clés des utilisateurs
  • Mettre en œuvre des mécanismes de révocation

Partie 1: Analyse des besoins et conception

Commencez par analyser les besoins du système et concevoir son architecture :

Besoins fonctionnels
  1. Gestion des utilisateurs
    • Création de comptes utilisateur
    • Génération et stockage sécurisé des clés
    • Émission de certificats X.509
  2. Gestion des documents
    • Upload de documents à signer
    • Stockage sécurisé des documents
    • Calcul d'empreintes cryptographiques
  3. Signature de documents
    • Signature avec la clé privée de l'utilisateur
    • Horodatage des signatures
    • Création de fichiers de signature
  4. Vérification de documents
    • Vérification des signatures cryptographiques
    • Validation des certificats
    • Vérification du statut de révocation
  5. Administration PKI
    • Gestion des autorités de certification
    • Révocation de certificats
    • Publication de CRLs/OCSP
Architecture du système
Composants principaux
  • Module PKI : Gestion des certificats et CAs
  • Module Document : Traitement et stockage des documents
  • Module Signature : Opérations cryptographiques
  • Module Utilisateur : Gestion des comptes et autorisations
  • Interface utilisateur : CLI ou application web
Technologies suggérées
  • Langage : Python 3.x
  • Bibliothèques crypto : cryptography, PyOpenSSL
  • Manipulation PDF : PyPDF2, reportlab
  • Base de données : SQLite ou PostgreSQL
  • Web (optionnel) : Flask ou Django
Utilisateurs Signataires Vérificateurs Interface utilisateur CLI ou Web (Signature et vérification) Administrateurs Gestion PKI Révocation Module PKI Gestion des certificats Module Utilisateur Comptes, Clés Module Signature Crypto, Validation Module Document Stockage, Hachage Stockage Documents, Certificats, Signatures, CRLs

Partie 2: Implémentation et fonctionnalités

Votre système devra implémenter au minimum les fonctionnalités suivantes :

Structure du projet
docsign/
├── README.md                  # Documentation du projet
├── requirements.txt           # Dépendances Python
├── docsign/
│   ├── __init__.py
│   ├── main.py                # Point d'entrée principal
│   ├── config.py              # Configuration du système
│   ├── pki/
│   │   ├── __init__.py
│   │   ├── ca.py              # Gestion de la CA
│   │   ├── certificates.py    # Opérations sur les certificats
│   │   └── crl.py             # Gestion des CRLs
│   ├── user/
│   │   ├── __init__.py
│   │   ├── models.py          # Modèle de données utilisateur
│   │   └── manager.py         # Gestion des utilisateurs
│   ├── document/
│   │   ├── __init__.py
│   │   ├── models.py          # Modèle de données document
│   │   └── manager.py         # Traitement des documents
│   ├── signature/
│   │   ├── __init__.py
│   │   ├── sign.py            # Fonctions de signature
│   │   └── verify.py          # Fonctions de vérification
│   ├── storage/
│   │   ├── __init__.py
│   │   └── db.py              # Accès à la base de données
│   └── ui/
│       ├── __init__.py
│       ├── cli.py             # Interface en ligne de commande
│       └── web.py             # Interface web (optionnelle)
├── data/
│   ├── ca/                    # Certificats et clés de la CA
│   ├── users/                 # Certificats et clés des utilisateurs
│   ├── documents/             # Documents et signatures
│   └── db/                    # Base de données
└── tests/
    ├── __init__.py
    ├── test_pki.py
    ├── test_user.py
    └── test_signature.py
Fonctionnalités essentielles
1. Initialisation du système PKI
# Exemple d'initialisation de la PKI
from docsign.pki.ca import CertificateAuthority

# Création de la CA racine
root_ca = CertificateAuthority(
    common_name="DocSign Root CA",
    organization="DocSign Security",
    country="FR",
    validity_days=3650
)
root_ca.initialize()

# Création d'une CA intermédiaire (optionnel)
intermediate_ca = root_ca.create_intermediate_ca(
    common_name="DocSign Signing CA",
    organization="DocSign Security",
    country="FR",
    validity_days=1825
)
intermediate_ca.initialize()
2. Gestion des utilisateurs
# Exemple de création d'utilisateur
from docsign.user.manager import UserManager

user_manager = UserManager(certificate_authority=intermediate_ca)

# Création d'un utilisateur avec certificat
new_user = user_manager.create_user(
    username="alice",
    email="alice@example.com",
    full_name="Alice Smith",
    password="secure_password",
    country="FR",
    organization="Example Corp"
)

# Récupération du certificat utilisateur
user_cert = user_manager.get_user_certificate("alice")
print(f"Certificate Subject: {user_cert.subject}")
print(f"Valid until: {user_cert.not_valid_after}")
3. Signature de document
# Exemple de signature de document
from docsign.signature.sign import DocumentSigner
from docsign.document.manager import DocumentManager

# Gestionnaire de documents
doc_manager = DocumentManager()

# Charger un document à signer
document = doc_manager.load_document("important_contract.pdf")

# Signer le document
signer = DocumentSigner(user_manager.get_user("alice"))
signature = signer.sign_document(
    document,
    reason="I approve this contract",
    location="Paris"
)

# Sauvegarder le document signé
doc_manager.save_signed_document(
    document,
    signature,
    output_path="signed_contract.pdf"
)
4. Vérification de signature
# Exemple de vérification de signature
from docsign.signature.verify import SignatureVerifier

# Créer un vérificateur
verifier = SignatureVerifier(trusted_ca=root_ca)

# Charger un document signé
signed_doc = doc_manager.load_signed_document("signed_contract.pdf")

# Vérifier la signature
verification_result = verifier.verify_signature(signed_doc)

if verification_result.is_valid:
    print(f"Signature valide!")
    print(f"Signé par: {verification_result.signer_name}")
    print(f"Date: {verification_result.signing_time}")
    print(f"Raison: {verification_result.reason}")
else:
    print(f"Signature invalide: {verification_result.error_message}")
5. Révocation de certificat
# Exemple de révocation de certificat
from docsign.pki.crl import CRLManager

# Gestionnaire de CRL
crl_manager = CRLManager(certificate_authority=intermediate_ca)

# Révoquer un certificat
crl_manager.revoke_certificate(
    user_manager.get_user_certificate("alice"),
    reason="keyCompromise"
)

# Générer une CRL mise à jour
crl_manager.generate_crl()

# Vérification avec CRL
verifier = SignatureVerifier(
    trusted_ca=root_ca,
    check_revocation=True,
    crl_manager=crl_manager
)

verification_result = verifier.verify_signature(signed_doc)
# Devrait détecter que le certificat a été révoqué

Partie 3: Interface utilisateur

Développez une interface utilisateur pour votre système. Vous pouvez choisir entre :

Interface en ligne de commande (CLI)

Implémentez une interface CLI qui permet aux utilisateurs d'effectuer toutes les opérations nécessaires :

#!/usr/bin/env python3
# cli.py - Interface CLI pour DocSign

import argparse
import sys
from docsign.user.manager import UserManager
from docsign.document.manager import DocumentManager
from docsign.signature.sign import DocumentSigner
from docsign.signature.verify import SignatureVerifier
from docsign.pki.ca import CertificateAuthority

def main():
    # Parser principal
    parser = argparse.ArgumentParser(description="DocSign - Système de signature de documents")
    subparsers = parser.add_subparsers(dest="command", help="Commande à exécuter")
    
    # Sous-commande: user
    user_parser = subparsers.add_parser("user", help="Gestion des utilisateurs")
    user_subparsers = user_parser.add_subparsers(dest="user_command")
    
    # user create
    user_create = user_subparsers.add_parser("create", help="Créer un utilisateur")
    user_create.add_argument("--username", required=True)
    user_create.add_argument("--email", required=True)
    user_create.add_argument("--fullname", required=True)
    user_create.add_argument("--password", required=True)
    
    # user list
    user_list = user_subparsers.add_parser("list", help="Lister les utilisateurs")
    
    # Sous-commande: sign
    sign_parser = subparsers.add_parser("sign", help="Signer un document")
    sign_parser.add_argument("--document", required=True, help="Chemin du document à signer")
    sign_parser.add_argument("--output", required=True, help="Chemin de sortie")
    sign_parser.add_argument("--username", required=True, help="Nom d'utilisateur du signataire")
    sign_parser.add_argument("--password", required=True, help="Mot de passe")
    sign_parser.add_argument("--reason", help="Raison de la signature")
    
    # Sous-commande: verify
    verify_parser = subparsers.add_parser("verify", help="Vérifier un document signé")
    verify_parser.add_argument("--document", required=True, help="Document signé à vérifier")
    
    # Sous-commande: revoke
    revoke_parser = subparsers.add_parser("revoke", help="Révoquer un certificat")
    revoke_parser.add_argument("--username", required=True)
    revoke_parser.add_argument("--reason", required=True)
    
    # Analyser les arguments
    args = parser.parse_args()
    
    # Exécuter la commande appropriée
    if args.command == "user":
        handle_user_command(args)
    elif args.command == "sign":
        handle_sign_command(args)
    elif args.command == "verify":
        handle_verify_command(args)
    elif args.command == "revoke":
        handle_revoke_command(args)
    else:
        parser.print_help()

def handle_user_command(args):
    # Implémentation des commandes utilisateur
    pass

def handle_sign_command(args):
    # Implémentation de la signature de document
    pass

def handle_verify_command(args):
    # Implémentation de la vérification de signature
    pass

def handle_revoke_command(args):
    # Implémentation de la révocation de certificat
    pass

if __name__ == "__main__":
    main()

Exemple d'utilisation :

# Créer un utilisateur
./docsign.py user create --username alice --email alice@example.com --fullname "Alice Smith" --password "secure_password"

# Signer un document
./docsign.py sign --document contract.pdf --output signed_contract.pdf --username alice --password "secure_password" --reason "I approve this contract"

# Vérifier un document signé
./docsign.py verify --document signed_contract.pdf

# Révoquer un certificat
./docsign.py revoke --username alice --reason "keyCompromise"
Interface web (optionnelle)

Pour les plus ambitieux, vous pouvez créer une interface web avec Flask :

# app.py - Application web Flask pour DocSign

from flask import Flask, render_template, request, redirect, url_for, flash, session
import os
from docsign.user.manager import UserManager
from docsign.document.manager import DocumentManager
from docsign.signature.sign import DocumentSigner
from docsign.signature.verify import SignatureVerifier

# Initialiser l'application
app = Flask(__name__)
app.secret_key = os.urandom(24)

# Configuration de l'application
app.config['UPLOAD_FOLDER'] = 'uploads'
os.makedirs(app.config['UPLOAD_FOLDER'], exist_ok=True)

# Initialiser les managers
user_manager = UserManager()
doc_manager = DocumentManager()
verifier = SignatureVerifier()

# Routes pour la gestion des utilisateurs
@app.route('/login', methods=['GET', 'POST'])
def login():
    if request.method == 'POST':
        username = request.form['username']
        password = request.form['password']
        
        if user_manager.authenticate(username, password):
            session['user'] = username
            flash('Connexion réussie!', 'success')
            return redirect(url_for('dashboard'))
        else:
            flash('Identifiants incorrects', 'danger')
    
    return render_template('login.html')

@app.route('/register', methods=['GET', 'POST'])
def register():
    if request.method == 'POST':
        # Traiter l'inscription
        pass
    
    return render_template('register.html')

# Routes pour la gestion des documents
@app.route('/dashboard')
def dashboard():
    if 'user' not in session:
        return redirect(url_for('login'))
    
    user = user_manager.get_user(session['user'])
    documents = doc_manager.get_user_documents(user.id)
    
    return render_template('dashboard.html', user=user, documents=documents)

@app.route('/upload', methods=['GET', 'POST'])
def upload_document():
    if 'user' not in session:
        return redirect(url_for('login'))
    
    if request.method == 'POST':
        # Traiter l'upload de document
        pass
    
    return render_template('upload.html')

@app.route('/sign/', methods=['GET', 'POST'])
def sign_document(document_id):
    if 'user' not in session:
        return redirect(url_for('login'))
    
    if request.method == 'POST':
        # Traiter la signature
        pass
    
    document = doc_manager.get_document(document_id)
    return render_template('sign.html', document=document)

@app.route('/verify', methods=['GET', 'POST'])
def verify_document():
    if request.method == 'POST':
        # Traiter la vérification
        pass
    
    return render_template('verify.html')

if __name__ == '__main__':
    app.run(debug=True)

Structure des templates :

templates/
├── base.html         # Template de base
├── dashboard.html    # Tableau de bord utilisateur
├── login.html        # Page de connexion
├── register.html     # Page d'inscription
├── sign.html         # Page de signature
├── upload.html       # Page d'upload de document
└── verify.html       # Page de vérification

Partie 4: Tests et démonstration

Développez des tests pour votre système et préparez une démonstration des fonctionnalités :

Tests unitaires
# tests/test_pki.py - Tests pour le module PKI

import unittest
import tempfile
import shutil
import os
from docsign.pki.ca import CertificateAuthority
from docsign.pki.crl import CRLManager

class TestCertificateAuthority(unittest.TestCase):
    def setUp(self):
        # Créer un répertoire temporaire pour les tests
        self.test_dir = tempfile.mkdtemp()
        self.ca_dir = os.path.join(self.test_dir, 'ca')
        os.makedirs(self.ca_dir)
    
    def tearDown(self):
        # Nettoyer après les tests
        shutil.rmtree(self.test_dir)
    
    def test_ca_initialization(self):
        # Tester la création d'une CA
        ca = CertificateAuthority(
            common_name="Test CA",
            organization="Test Org",
            country="FR",
            validity_days=365,
            storage_path=self.ca_dir
        )
        ca.initialize()
        
        # Vérifier que les fichiers ont été créés
        self.assertTrue(os.path.exists(os.path.join(self.ca_dir, 'ca.key')))
        self.assertTrue(os.path.exists(os.path.join(self.ca_dir, 'ca.crt')))
    
    def test_certificate_issuance(self):
        # Créer une CA
        ca = CertificateAuthority(
            common_name="Test CA",
            organization="Test Org",
            country="FR",
            validity_days=365,
            storage_path=self.ca_dir
        )
        ca.initialize()
        
        # Émettre un certificat
        cert = ca.issue_certificate(
            common_name="Test User",
            organization="Test Org",
            country="FR",
            email="test@example.com",
            validity_days=365
        )
        
        # Vérifier le certificat
        self.assertEqual(cert.subject.get_attributes_for_oid(0)[0].value, "Test User")
        self.assertEqual(cert.issuer.get_attributes_for_oid(0)[0].value, "Test CA")
    
    def test_certificate_revocation(self):
        # Créer une CA
        ca = CertificateAuthority(
            common_name="Test CA",
            organization="Test Org",
            country="FR",
            validity_days=365,
            storage_path=self.ca_dir
        )
        ca.initialize()
        
        # Émettre un certificat
        cert = ca.issue_certificate(
            common_name="Test User",
            organization="Test Org",
            country="FR",
            email="test@example.com",
            validity_days=365
        )
        
        # Créer un gestionnaire de CRL
        crl_manager = CRLManager(certificate_authority=ca)
        
        # Révoquer le certificat
        crl_manager.revoke_certificate(cert, reason="keyCompromise")
        
        # Générer une CRL
        crl = crl_manager.generate_crl()
        
        # Vérifier que le certificat est dans la CRL
        self.assertTrue(crl_manager.is_certificate_revoked(cert))

if __name__ == '__main__':
    unittest.main()
Scénario de démonstration

Préparez un script de démonstration qui montre toutes les fonctionnalités de votre système :

  1. Initialisation : Créez une PKI avec une CA racine et une CA intermédiaire
  2. Gestion des utilisateurs : Créez plusieurs utilisateurs avec des certificats
  3. Signature de documents : Signez un document PDF avec différents utilisateurs
  4. Vérification des signatures : Vérifiez les signatures des documents
  5. Révocation : Révoquez un certificat et montrez que les signatures correspondantes sont invalidées
  6. Validation de chaîne : Montrez comment la chaîne de certification est validée
#!/usr/bin/env python3
# demo.py - Script de démonstration pour DocSign

import os
import sys
import time

# Ajouter le répertoire parent au path pour pouvoir importer les modules
sys.path.insert(0, os.path.abspath(os.path.join(os.path.dirname(__file__), '..')))

from docsign.pki.ca import CertificateAuthority
from docsign.user.manager import UserManager
from docsign.document.manager import DocumentManager
from docsign.signature.sign import DocumentSigner
from docsign.signature.verify import SignatureVerifier
from docsign.pki.crl import CRLManager

def clear_screen():
    """Efface l'écran du terminal."""
    os.system('cls' if os.name == 'nt' else 'clear')

def pause():
    """Attendre que l'utilisateur appuie sur Entrée."""
    input("\nAppuyez sur Entrée pour continuer...")
    clear_screen()

def print_header(title):
    """Affiche un titre formaté."""
    print("\n" + "=" * 60)
    print(f" {title}")
    print("=" * 60 + "\n")

def run_demo():
    """Exécute la démonstration complète du système DocSign."""
    clear_screen()
    print_header("DÉMO DU SYSTÈME DOCSIGN")
    print("Ce script va démontrer toutes les fonctionnalités du système.")
    pause()
    
    # Étape 1: Initialisation de la PKI
    print_header("1. INITIALISATION DE LA PKI")
    print("Création de l'autorité de certification racine...")
    
    # Créer un répertoire pour la démo si nécessaire
    demo_dir = "demo_data"
    os.makedirs(demo_dir, exist_ok=True)
    
    # Créer la CA racine
    root_ca = CertificateAuthority(
        common_name="DocSign Root CA",
        organization="DocSign Security",
        country="FR",
        validity_days=3650,
        storage_path=os.path.join(demo_dir, "root_ca")
    )
    root_ca.initialize()
    print("✓ CA racine créée avec succès!")
    
    print("\nCréation de l'autorité de certification intermédiaire...")
    intermediate_ca = root_ca.create_intermediate_ca(
        common_name="DocSign Signing CA",
        organization="DocSign Security",
        country="FR",
        validity_days=1825,
        storage_path=os.path.join(demo_dir, "intermediate_ca")
    )
    intermediate_ca.initialize()
    print("✓ CA intermédiaire créée avec succès!")
    
    # Afficher les détails des certificats
    print("\nDétails du certificat racine:")
    root_cert_info = root_ca.get_certificate_info()
    print(f"  Sujet: {root_cert_info['subject']}")
    print(f"  Émetteur: {root_cert_info['issuer']}")
    print(f"  Validité: {root_cert_info['valid_from']} au {root_cert_info['valid_to']}")
    
    print("\nDétails du certificat intermédiaire:")
    inter_cert_info = intermediate_ca.get_certificate_info()
    print(f"  Sujet: {inter_cert_info['subject']}")
    print(f"  Émetteur: {inter_cert_info['issuer']}")
    print(f"  Validité: {inter_cert_info['valid_from']} au {inter_cert_info['valid_to']}")
    
    pause()
    
    # Étape 2: Création des utilisateurs
    print_header("2. CRÉATION DES UTILISATEURS")
    print("Initialisation du gestionnaire d'utilisateurs...")
    user_manager = UserManager(
        certificate_authority=intermediate_ca,
        storage_path=os.path.join(demo_dir, "users")
    )
    
    # Créer plusieurs utilisateurs
    users = [
        {"username": "alice", "email": "alice@example.com", "full_name": "Alice Smith", "password": "password123"},
        {"username": "bob", "email": "bob@example.com", "full_name": "Bob Johnson", "password": "password456"},
        {"username": "charlie", "email": "charlie@example.com", "full_name": "Charlie Brown", "password": "password789"}
    ]
    
    for user_data in users:
        print(f"\nCréation de l'utilisateur {user_data['username']}...")
        user = user_manager.create_user(
            username=user_data['username'],
            email=user_data['email'],
            full_name=user_data['full_name'],
            password=user_data['password'],
            country="FR",
            organization="Demo Corp"
        )
        print(f"✓ Utilisateur {user_data['username']} créé avec succès!")
        
        # Afficher les détails du certificat utilisateur
        cert_info = user_manager.get_user_certificate_info(user_data['username'])
        print(f"  Certificat émis pour: {cert_info['subject']}")
        print(f"  Émis par: {cert_info['issuer']}")
        print(f"  Validité: {cert_info['valid_from']} au {cert_info['valid_to']}")
    
    pause()
    
    # Étape 3: Création et signature de documents
    print_header("3. SIGNATURE DE DOCUMENTS")
    print("Initialisation du gestionnaire de documents...")
    doc_manager = DocumentManager(storage_path=os.path.join(demo_dir, "documents"))
    
    # Créer un document de test
    sample_doc_path = os.path.join(demo_dir, "sample_document.txt")
    with open(sample_doc_path, "w") as f:
        f.write("Ceci est un document de test pour la démonstration du système DocSign.\n")
        f.write("Il sera signé par différents utilisateurs pour montrer les fonctionnalités du système.\n")
        f.write("Date: " + time.strftime("%Y-%m-%d %H:%M:%S"))
    
    print(f"✓ Document de test créé: {sample_doc_path}")
    
    # Charger le document
    document = doc_manager.load_document(sample_doc_path)
    print("✓ Document chargé avec succès!")
    
    # Signer le document avec différents utilisateurs
    for username in ["alice", "bob"]:
        print(f"\nSignature du document par {username}...")
        signer = DocumentSigner(user_manager.get_user(username))
        signature = signer.sign_document(
            document,
            reason=f"Approuvé par {username}",
            location="Paris"
        )
        
        # Sauvegarder le document signé
        signed_path = os.path.join(demo_dir, f"document_signed_by_{username}.txt")
        doc_manager.save_signed_document(document, signature, output_path=signed_path)
        print(f"✓ Document signé par {username} sauvegardé: {signed_path}")
    
    pause()
    
    # Étape 4: Vérification des signatures
    print_header("4. VÉRIFICATION DES SIGNATURES")
    print("Initialisation du vérificateur de signatures...")
    verifier = SignatureVerifier(trusted_ca=root_ca)
    
    # Vérifier les signatures
    for username in ["alice", "bob"]:
        signed_path = os.path.join(demo_dir, f"document_signed_by_{username}.txt")
        print(f"\nVérification de la signature de {username}...")
        signed_doc = doc_manager.load_signed_document(signed_path)
        
        verification_result = verifier.verify_signature(signed_doc)
        
        if verification_result.is_valid:
            print(f"✓ Signature valide!")
            print(f"  Signé par: {verification_result.signer_name}")
            print(f"  Date: {verification_result.signing_time}")
            print(f"  Raison: {verification_result.reason}")
        else:
            print(f"✗ Signature invalide: {verification_result.error_message}")
    
    pause()
    
    # Étape 5: Révocation de certificat
    print_header("5. RÉVOCATION DE CERTIFICAT")
    print("Initialisation du gestionnaire de CRL...")
    crl_manager = CRLManager(
        certificate_authority=intermediate_ca,
        storage_path=os.path.join(demo_dir, "crl")
    )
    
    # Révoquer le certificat de Bob
    print("Révocation du certificat de Bob...")
    crl_manager.revoke_certificate(
        user_manager.get_user_certificate("bob"),
        reason="keyCompromise"
    )
    
    # Générer une CRL mise à jour
    crl = crl_manager.generate_crl()
    print("✓ CRL générée avec succès!")
    
    # Afficher les certificats révoqués
    revoked_certs = crl_manager.list_revoked_certificates()
    print("\nCertificats révoqués:")
    for cert in revoked_certs:
        print(f"  - Numéro de série: {cert['serial_number']}")
        print(f"    Révoqué le: {cert['revocation_date']}")
        print(f"    Raison: {cert['reason']}")
    
    pause()
    
    # Étape 6: Vérification avec révocation
    print_header("6. VÉRIFICATION AVEC RÉVOCATION")
    print("Initialisation du vérificateur avec vérification de révocation...")
    verifier_with_crl = SignatureVerifier(
        trusted_ca=root_ca,
        check_revocation=True,
        crl_manager=crl_manager
    )
    
    # Vérifier les signatures avec vérification de révocation
    for username in ["alice", "bob"]:
        signed_path = os.path.join(demo_dir, f"document_signed_by_{username}.txt")
        print(f"\nVérification de la signature de {username} (avec CRL)...")
        signed_doc = doc_manager.load_signed_document(signed_path)
        
        verification_result = verifier_with_crl.verify_signature(signed_doc)
        
        if verification_result.is_valid:
            print(f"✓ Signature valide!")
            print(f"  Signé par: {verification_result.signer_name}")
            print(f"  Date: {verification_result.signing_time}")
        else:
            print(f"✗ Signature invalide: {verification_result.error_message}")
    
    pause()
    
    # Conclusion
    print_header("CONCLUSION DE LA DÉMONSTRATION")
    print("La démonstration est terminée. Nous avons montré :")
    print("1. La création d'une PKI complète avec CA racine et intermédiaire")
    print("2. La gestion des utilisateurs et de leurs certificats")
    print("3. La signature numérique de documents")
    print("4. La vérification des signatures")
    print("5. La révocation de certificats")
    print("6. L'impact de la révocation sur la vérification des signatures")
    
    print("\nTous les fichiers générés se trouvent dans le répertoire:", demo_dir)
    print("\nMerci d'avoir suivi cette démonstration!")

if __name__ == "__main__":
    run_demo()

Partie 5: Critères d'évaluation

Votre projet sera évalué selon les critères suivants :

  • Fonctionnalités : Implémentation correcte des fonctionnalités requises
  • Architecture : Organisation du code, modularité, extensibilité
  • Sécurité : Bonnes pratiques cryptographiques, gestion sécurisée des clés
  • Interface utilisateur : Convivialité, clarté, gestion des erreurs
  • Documentation : Documentation du code, manuel utilisateur
  • Tests : Couverture et qualité des tests

Prérequis

Logiciels nécessaires
  • OpenSSL (version 1.1.1 ou supérieure)
  • Python 3.7+ (pour les scripts d'analyse)
  • Docker (pour le TP 3 sur l'authentification mutuelle)
Bibliothèques Python
# Installation des dépendances
pip install cryptography pyOpenSSL requests flask
# Pour le TP 4 (projet)
pip install PyPDF2 reportlab
Connaissances requises
  • Concepts de cryptographie asymétrique
  • Bases de l'utilisation d'OpenSSL
  • Programmation Python (pour les TPs 3 et 4)