TP Sécurisation des Communications : Cryptographie
Certificats HTTPS
Observer le certificat de ce site en cliquant sur le cadenas. Trouvez
- sa date d'expiration
- le nom de l'émetteur
- l'émetteur du certificat est-il directement une autorité de certification ? On parle de chaîne de certificats quand une autorité certifie quelqu'un qui a son tour certifie quelqu'un d'autre.
Vous devez pouvoir trouver la clé publique du site.
- Quel algorithme est utilisé ?
- Quelle est la taille de la clé ?
- Quel est l'exposant e de chiffrement ? (cela signifie qu'un message
M
sera chiffré par le reste deM^e
dans la division euclidienne par le module) - Dans quel encodage (base) est affiché le module dans Firefox ?
Clés SSH
On a vu au précédent TP que ssh est un protocole (et un logiciel, la commande associée) qui permet de se connecter de manière chiffrée sur une autre machine et d'y avoir un terminal.
Sur linux, si un utilisateur les a générées, il dispose d'une clé ssh publique .ssh/id_rsa.pub
et d'une clé ssh privée .ssh/id_rsa
. Affichez les deux dans le terminal avec la commande cat
. Avec quel encodage sont-elles affichées ? (combien de caractères possibles à votre avis ? c'est une puissance de 2)
La clé privée sert à décoder les messages chiffrés reçus, mais peut aussi servir à se connecter sur un serveur en s'authentifiant, remplaçant ainsi le mot de passe :
- Si on veut s'authentifier sur un serveur avec notre clé publique, on ajoute le contenu de
.ssh/id_rsa.pub
au fichier.ssh/authorized_keys
du serveur et on autorise l'identification par clé dans les paramètres du serveur ssh (/etc/ssh/sshd_config
sur le serveur). - Le serveur autorise la connection à la personne qui peut prouver qu'elle dispose de la clé privée associée à cette clé publique (en signant un message dans le protocole).
On désactive en général alors l'identification par mot de passe, ce qui permet d'éviter toutes les attaques qui essaient de deviner un mot de passe faible.
Masque jetable (xor bit à bit) en python
Pour faire le XOR bit-à-bit d'un message, il faut se mettre d'accord sur la représentation binaire du texte. Cela dépend de l'encodage choisi.
Pour vous en rendre compte, essayez successivement dans une console python:
"départ".encode("ascii")
"départ".encode("iso-8859-1")
"départ".encode("utf-8")
Info
- L'affichage
\xe9
signifiee9
en hexadécimal. Un octet peut en effet toujours être représenté par 2 chiffres hexadécimaux (ou bien 8 chiffres binaires, ou bien un nombre décimal entre 0 et 255) - Le résultat, affiché sous la forme
b'blabla'
en python, est du typebytes
qui permet de représenter des valeurs d'octets brutes (sans se soucier de si ça représente un texte valide ou non). La valeur d'un octet est affiché en caractère si c'est un code ASCII valide, et sous la forme\x??
sinon.
Écrire une fonction xor_octet(a,b)
qui effectue le xor sur deux octets a et b de type int, et renvoie
le résultat sous forme d'une valeur de type bytes de longueur 1.
- pour faire le XOR bit-à-bit sur des nombres en python, on utilise l'opérateur
^
- pour convertir un int en bytes, on utilise la méthode suivante :
(56).to_bytes(length=1,byteorder="big")
Écrire une fonction chiffrage_xor(m,key)
qui :
- prend un paramètre m de type bytes (le message), et un paramètre key de type bytes (la clé)
- si la longueur de la clé est plus petite que celle du message, renvoie
None
- sinon, parcourt tous les octets
m[i]
dem
, et les chiffre en utilisantxor_octet
avec la clékey[i]
. On pourra créer une variableresultat
initialisée àb''
(de type bytes et vide), et ajouter les octets à la fin avecresultat += ...
. - renvoie le résultat chiffré de type bytes
Créez des variables avec une clé et un message (de type bytes), et tester votre fonction. Comment faire le déchiffrage ?
Essayez l'exercice suivant :
# on suppose que clé et message1 ont été définis
# et qu'on a obtenu message1_chiffre à partir de clé
message2 = b'jecontrolecemessage'
message2_chiffre = chiffrage_xor(message2, clé)
# on a réutilisé deux fois la même clé, ce qui rend le chiffrement attaquable
# Retrouvez message1 seulement à partir de message1_chiffre, message2, message2_chiffre
# (sans utiliser la clé)
Attaque temporelle
On a vu que ce code :
def verifie(mot_de_passe, mot):
"""Renvoie True si et seulement si mot == mot_de_passe"""
n = len(mot_de_passe)
if len(mot) != n:
return False
for i in range(n):
if mot[i] != mot_de_passe[i]:
return False
return True
est correct mais permet de deviner une petite information en fonction du temps mis à répondre : plus on a de caractères corrects au début du mot (s'il a la bonne taille), plus on va faire de tours dans la boucle for avant de s'arrêter.
Cela permet une attaque par canal auxiliaire, qu'on va essayer de faire marcher concrètement.
Téléchargez et décompressez timing_attack.zip puis complétez le fichier timing_attack_eleve.py
pour essayer
de deviner le mot de passe contenu dans crypto_trouee.py
juste en appelant la fonction verifie
, en bien moins d'un milliard d'années...
Utilisation de bibliothèques pour RSA, AES, ...
S'il est très conseillé de recoder de la cryptographie soi-même, pour le fun et pour apprendre comment ça marche (voir section suivante), il ne faut pas le faire pour des vrais projets qui seront utilisés par d'autres gens !
Installez la bibliothèque cryptography
, et utilisez la documentation
pour :
À faire
déchiffrer le message b'gAAAAABiMifXdoh1jmgSvLyg6DtoXtZGL-R-AT0w00a407KrfUIw1uVTPU7iBuR6U8zugq873etsFjixkbF8TXH8iNRFP4T8WjaKFq39oBjpSC3SmL-zkB3AL7j8UUmLZFsolSfZ_PIlZfnjzbYWj9CTkUrEyHP0M0VPcN6GvyS1IVhOrGIrPuEv9LbkjBKy6sqG4XIgUJ-2-PHRnRxIb-Wz54g6OLvJ34Uq896jgQdtuV8EZen6rUnYchVAwJKMRMzAHoSSx-DT'
chiffré avec le module de chiffrement symétrique Fernet et la clé b'L28Yw473ZH8mjAnP0B3LH-XGX_kcjPHg7Kqz8yAaB8k='
Quelles sont les deux limitations de sécurité mentionnées sur la documentation de la biibliothèque ? Essayez de les comprendre, et appelez-moi pour me les réexpliquer.
Pour aller plus loin
Le site https://cryptopals.com/ contient une série de 48 exercices qui peuvent se résoudre en python et qui font coder des attaques concrètes sur des procédés de cryptographie. Il faut un peu d'aisance en programmation mais il n'y a pas besoin de beaucoup de maths : la plupart des attaques n'utilisent que des maths élémentaires. Ça prend du temps mais c'est très recommandé si vous avez envie de savoir dans les détails comment fonctionne et comment se casse la cryptographie moderne.