Vous devrez utiliser l'interface TPLab pour envoyer vos TP aux encadrants de TP.
Pour ce TP, vous devrez envoyer un message (signé et crypté) contenant un petit rapport.
Le rapport sera devra être un fichier texte. Les rapports envoyés dans un autre format (pdf, openoffice, openrtf, word) ne seront pas lus.
Faites attention lors de la rédaction du rapport : je ne veux pas lire la suite des commandes que vous avez utilisées. Soyez concis...
Vos mots de passe pour vous connecter à votre compte Facebook, univ-savoie
ou tout autre service necessitant une authentification ne sont normalement pas stockés directement dans un fichier. Le risque de fuite serait trop important...
Normalement, seul un hash de votre mot de passe est enregistré sur un ordinateur : un hash est une suite de caractères de taille fixe associée à une chaîne quelconque. Par exemple, le hash (pour l'algorithme sha1) de la chaîne
J'aime les pizzas.
est "ac4f7e9c94319a21136f8e5f9189bdaf7899c25e"
. Pour la chaîne
j'aime les pizzas.
(sans majuscule), le hash est maintenant "2edba57751b915a8dd8d562e1179265f5d16088c
"
Le hash de
Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.
est "63990c1f17df756f8d7cb96cdf18e933b66ec0f0
" et contient exactement le même nombre de caractères que les hash précédents...
Les fonctions de hash utilisées en cryptographie sont toujours faciles (rapide) à calculer, mais elles doivent vérifient )les propriétés suivantes :
Les algorithmes de hashage les plus connus sont :
Pour vous authentifier sur un site, vous tapez votre mot de passe, et le programme vérifie que son hash est bien identique au hash stocké sur le serveur...
Expliquez pourquoi il n'est pas possible, même pour l'administrateur du serveur, de retrouver votre mot de passe en cas de perte...
Si on possède le hash d'un mot de passe, on peut essayer de retrouver le mot de passe en essayant toutes les possibilités.
En général, il est intéressant de commencer par les mots du dictionnaire. Le fichier dico.txt contient les mots du dictionnaire "le Littré" qui ne contiennent pas d'accent. Il contient 47666 mots...
Le code Python suivant permet de tester tous les mots de ce fichier et de comparer leur hash avec un hash passé en argument :
import hashlib from datetime import datetime def attaque_dico_hash(h, dic): dico = open(dic, mode="r") n = 0 # pour compter le nombre de mots t0 = datetime.now() # l'heure à l'instant présent for mot in dico: mot = mot.strip() n = n + 1 if hashlib.sha256(mot.encode()).hexdigest() == h: print() print("TROUVÉ ! Le mot '{}' a le hash {},".format(mot,h)) print("{} mot(s) ont étés testés en {} seconde(s).".format(n, (datetime.now()-t0).total_seconds())) dico.close() return if n % 1000 == 0: print(".", end="") print() print("{} mot(s) ont étés testés en {} seconde(s),".format(n, (datetime.now()-t0).total_seconds())) print("Aucun des mots testés n'avait le hash {}.".format(h))
Utilisez ce morceau de code pour retrouver le mot de passe correspondant au hash
11f48731001d3a8e81b2305036b5cb2a19309d7fe86983e05fe16a2cb900e522
Pour le second mot de passe, j'ai :
Le hash est maintenant
2a2ec0d82a404e4bb0988ea6998f4ad5d0e8e87df2cb6a288e6191a75f658406
Retrouvez le mot de passe...
Combien de temps est-ce que la recherche prend ?
Nous allons maintenant tester tous les mots de passe d'une taille donnée. Pour les mots de passe sur 3 lettres, cela pourrait donner :
import hashlib from datetime import datetime def attaque_brute_force_hash(h): n = 0 # pour compter le nombre de mots t0 = datetime.now() # l'heure à l'instant présent alphabet = "abcdefghijklmnopqrstuvwxyz" for a in alphabet: for b in alphabet: for c in alphabet: mot = a+b+c n = n + 1 if hashlib.sha256(mot.encode()).hexdigest() == h: print() print("TROUVÉ ! '{}' a le hash {},".format(mot,h)) print("{} mot(s) ont étés testés en {} seconde(s).".format(n, (datetime.now()-t0).total_seconds())) return if n % 1000 == 0: print(".", end="") print() print("{} mot(s) ont étés testés en {} seconde(s),".format(n, (datetime.now()-t0).total_seconds())) print("Aucun des mots testés n'avait le hash {}.".format(h))
Vérifiez que vous retrouvez bien le mot de passe de 3 lettre pour le hash
52a408a9e3ec559f30a16ca8baf40761c9607e8755f63599957de2f6412a0005
Combien de temps est-ce que cela prend ?
Modifiez le programme pour qu'il teste tous les mots de passe de 4 lettres, et recherchez le mot de passe pour le hash
e13b5b56520b1aa82029053158f2b017816a4e9618da08e82703c05a9d8628c1
Combien de temps est-ce que cela prend ?
Modifiez le programme pour qu'il teste tous les mots de passe de 5 lettres, et recherchez le mot de passe pour le hash
7fd2e09b9e362ece70e60489dd8a082ea6118cbdae94a7866e9617c3deab0939
Combien de temps est-ce que cela prend ?
Combien de mots de passe arrivez vous à tester en une seconde ?
Facultatif modifiez le programme pour qu'il teste tous les mots de passe de 6 lettres, et recherchez le mot de passe pour le hash
c6377a082e51ca6ede28b7987003151b322123fdb663c154db3bc0611c2d5d01
Combien de temps est-ce que cela prend ?
Le but de la suite de ce TP est de vous familiariser avec la notion de signature électronique et de chiffrement clé publique / clé privée en utilisant le logiciel GPG (Gnu Privacy Guard : http://www.gnupg.org/). GPG est une version libre du logiciel PGP (Pretty Good Privacy : http://www.pgp.com/) crée par Philip Zimmermann. Bien qu'il existe des clients graphique (GPA par exemple), nous allons utilisez l'outil le plus basique (mais aussi le plus puissant) : le programme gpg
en mode texte.
Dans un terminal (Menu Applications --> Accessoire --> Terminal
, vérifiez que le logiciel est bien installé avec la commande
$ gpg --version
Créez ensuite un répertoire dans le bureau et positionnez-vous dans ce répertoire :
$ mkdir Bureau/info223-TP3 $ cd Bureau/info223-TP3
$
" au début de chaque ligne représente l'invite de commande. Vous ne devez pas les écrire ...
cd Bureau/info223-TP3
.
Tab
.
Si vous partagez une clé secrète avec votre destinataire, vous pouvez utiliser GPG pour faire de la cryptographie symétrique. Pour crypter un fichier, il faut utiliser la commande :
$ gpg --symmetric --armour LE_NOM_DU_FICHIER_QUE_VOUS_VOULEZ_CRYPTER
Ceci créera un fichier avec l'extension ".asc
" contenant le fichier chiffré. Cette méthode est préférée quand vous voulez par exemple envoyer le fichier par email.
Vous pouvez également créer un fichier crypté binaire. La commande correspondante est
$ gpg --symmetric LE_NOM_DU_FICHIER_QUE_VOUS_VOULEZ_CRYPTER
Ceci créera un fichier binaire avec l'extension ".gpg
" contenant le fichier binaire chiffré.
Utilisez cette commande pour créer un fichier crypté. Vérifier qu'en modifiant un tout petit peu la clé ou le contenu du fichier, le contenu du fichier crypté change énormément.
Vous pouvez pour ceci utiliser un gros fichier texte et regarder ce qui se passe dans le fichier crypté en l'ouvrant avec un éditeur de texte (gedit
ou autre).
Pour décrypter, il suffit d'utiliser :
$ gpg --decrypt LE_NOM_DU_FICHIER_QUE_VOUS_VOULEZ_DÉCRYPTER.asc
(Bien entendu, l'extension ".asc
" sera remplacé par ".gpg
" si le fichier a été crypté en binaire..)
On peut essayer une attaque "brute force" comme pour les mots de passe. Le code suivant permet de lancer la commande gpg --decrypt
sur un fichier existant. Elle teste toutes les lignes d'un autre fichier comme clé...
import os import subprocess from datetime import datetime def attaque_dico_gpg(fichier, dic): if not os.path.isfile(fichier): print("Le fichier {} n'existe pas.".format(fichieR)) return dico = open(dic, mode="r") n = 0 # pour compter les mots t0 = datetime.now() # l'heure à l'instant présent # tableau contenant les différents morceau de la commande à executer... # il faudra remplacer "CLE SECRETE" par la clé que l'on veut tester commande = ["gpg", "--quiet", "--batch", "--no-use-agent", "--decrypt", "--passphrase", "CLE SECRETE", fichier] NULL = open(os.devnull, mode="a") for mot in dico: mot = mot.strip() n = n + 1 commande[-2] = mot res = subprocess.call(commande, stdout=NULL, stderr=NULL) if res == 0: print() print("TROUVÉ ! Le mot '{}' est la clé secrète pour décrypter le fichier {},".format(mot, fichier)) print("{} mot(s) ont étés testés en {} seconde(s).".format(n, (datetime.now()-t0).total_seconds())) return if n % 1000 == 0: print(".", end="") print("{} mot(s) ont étés testés en {} seconde(s),".format(n, (datetime.now()-t0).total_seconds())) print("Aucun des mots testés ne permet de décrypter le fichier {}.".format(fichier))
Utilisez ce programme pour retrouver la clé décryptant le fichier suivant...
Combien de clés pouvez-vous tester en une seconde ?
Si le programme Python ne trouve pas la commande gpg
, vous devrez remplacer la ligne
commande = ["gpg", "--quiet", "--batch", "--no-use-agent", "--decrypt", "--passphrase", "CLE SECRETE", fichier]
par
commande = ["CHEMIN_COMPLET_DU_PROGRAMME_gpg", "--quiet", "--batch", "--no-use-agent", "--decrypt", "--passphrase", "CLE SECRETE", fichier]
où CHEMIN_COMPLET_DU_PROGRAMME_gpg
est le résultat de la commande
$ which gpg
par exemple, /usr/local/bin/gpg
...
Les clés sont stockées dans un répertoire caché de votre répertoire personnel : .gnupg
. Vous êtes la seule personne à avoir accès à ce fichier. De plus, vos clés sont protégées par un mot de passe pour renforcer la sécurité.
Pour créer votre propre clé publique/clé privée, il faut utiliser la commande
$ gpg --gen-key
Remarque : si GPG vous dis qu'il n'a pas assez d'entropie, il faut faire travailler le processeur. Vous pouvez utiliser la commande $ ls -R /usr/
dans un autre terminal et attendre un peu...
Pour vérifiez que les clés ont bien été créées, utilisez la commande
$ gpg --list-keys
Vous devriez obtenir quelque chose du genre
$HOME/.gnupg/pubring.gpg pub 2048R/9623ABA3 2014-04-24 [expire : 2014-05-24] uid Pierre Hyvernat (clé temporaire, TP3 info223) <pierre.hyvernat@univ-savoie.fr> sub 2048R/32DB7919 2014-04-24 [expire : 2014-05-24]
qui vous indique que vous avez une clé principale (ligne "pub
") qui expire le 24 mai ; et une sous-clé (ligne "sub
") qui expire aussi le 24 mai. La ligne "uid
" vous donne l'identité de l'utilisateur correspondant.
La clé principale est utilisé pour les signatures, et la sous-clé pour le chiffrement.
Créez votre propre clé et vérifiez son existence.
ATTENTION : votre clé secrète doit rester secrète. Si quelqu'un y a accès, il peut usurper votre identité et lire les messages chiffrés qui vous sont adressés. Votre passphrase doit en garantir la sécurité, car c'est la seul protection que vous avez si quelqu'un peut accéder à votre compte... Choisissez donc une passphrase sûre, et ne la dévoilez à personne.
Ceci est d'autant plus important si vous avez distribué votre clé publique...
Pour envoyer votre clé publique à quelqu'un, vous pouvez commencer par l'exporter avec la commande
$ gpg --output cle.asc --export --armour IDENTITÉ_DE_LA_CLÉ_À_EXPORTER
où "IDENTITÉ_DE_LA_CLÉ_À_EXPORTER
" est l'identité (l'adresse email par exemple) de la clé concernée et "cle.asc
" le nom du fichier qui contiendra la clé en ASCII.
Si vous voulez exporter la clé en binaire, il faut utiliser :
$ gpg --output cle.gpg --export IDENTITÉ_DE_LA_CLÉ_À_EXPORTER
À l'inverse, pour importer une clé (en binaire ou en ASCII) contenue dans le fichier "cle.asc
", il suffit d'utiliser la commande
$ gpg --import cle.asc
$ gpg --list-keys
".
Pour faciliter le partage de clé, il est également possible d'utiliser un annuaire de clé. Nous n'en utiliserons pas pour ce TP.
Chaque clé possède une « empreinte digitale ». Quand vous récupérez une clé, il est important de vérifier cette empreinte... Cette empreinte est suffisamment petite pour être facilement transmissible (carte de visite etc.)
Par exemple, nos clés possèdent l'empreinte
0AA3 4777 06C9 61A0 02D2 7AEB DF14 C879 9623 ABA3
(lien vers la clé)
0C15 6485 DA9B ADE3 99D8 5557 10A1 6EF7 22D8 E2EF
(lien vers la clé)
Comme on ne peut pas faire confiance à une page web, je vous l'écrirais au tableau...
Pour trouver l'empreinte d'une clé, vous pouvez utiliser
$ gpg --fingerprint
qui listera toutes les clés connues avec leur empreinte. Si vous mettez une chaîne de caractères à la fin de la commande, cela ne listera que les clés qui contiennent la chaîne en question. (Pratique quand vous avez beaucoup de clés.)
Une fois que vous avez vérifié une clé, vous pouvez l'authentifier pour dire « je fais confiance à cette clé... » On parle de contre-signature. La commande est simplement :
$ gpg --sign-key IDENTITÉ_DE_LA_CLÉ_QUE_VOUS_VOULEZ_AUTHENTIFIER
où "IDENTITÉ_DE_LA_CLÉ_QUE_VOUS_VOULEZ_AUTHENTIFIE
" est l'identité de la clé à authentifier (par exemple, l'adresse email correspondante).
Pour obtenir la liste des signatures sur les clés que vous possèdez, il faut utiliser la commande
$ gpg --list-sigs
Maintenant que vous avez des clés, vous pouvez crypter des messages sans partager de clés secrètes...
On utilise
$ gpg --encrypt --armour LE_NOM_DU_FICHIER_QUE_VOUS_VOULEZ_CRYPTER
pour obtenir un fichier ASCII avec l'extension ".asc
" contenant le fichier original crypté. GPG nous demandera les destinataires, à choisir parmi les gens dont on possède les clés publiques.
Si on veut obtenir un fichier binaire, la commande devient :
$ gpg --encrypt LE_NOM_DU_FICHIER_QUE_VOUS_VOULEZ_CRYPTER
pour obtenir un fichier avec l'extension ".gpg
" contenant le fichier original crypté.
Toujours pareil : pour décrypter, on utilise
$ gpg --decrypt LE_NOM_DU_FICHIER_QUE_VOUS_VOULEZ_DÉCRYPTER
Testez le cryptage / décryptage avec votre voisin...
Maintenant que vous avez des clés, vous pouvez signer des messages. Pour cela, il faut utiliser :
$ gpg --clearsign LE_NOM_DU_FICHIER_QUE_VOUS_VOULEZ_SIGNER
pour signer le fichier "LE_NOM_DU_FICHIER_QUE_VOUS_VOULEZ_SIGNER
". Ceci créera un nouveau fichier avec l'extension ".asc
" qui contiendra le fichier original avec une signature vous authentifiant.
La commande
$ gpg --detach-sign LE_NOM_DU_FICHIER_QUE_VOUS_VOULEZ_SIGNER
permet elle de créer uniquement une signature (binaire) pour le fichier en question. Cette signature (fichier avec l'extension ".sig
") devra être envoyé avec le fichier original.
Pour un fichier texte, la première méthode est préférable. (Sauf si c'est un email et que votre logiciel gère les signatures en pièce jointe...) Pour un fichier binaire, il faut mieux utiliser la seconde méthode.
Pour vérifier un fichier signé, on utilise
$ gpg --verify LE_NOM_DU_FICHIER_QUE_VOUS_VOULEZ_VÉRIFIER.asc
Il faut bien entendu pour cela disposer de la clé publique de la personne qui a signé le document.
Deux versions du sujet du TP signé se trouvent ici et là.
Si vous voulez crypter et signer un fichier, quels sont les différences entre :
uid
" est votre adresse email pour choisir votre clé)
$ gpg --output cle_privee.asc --export-secret-key --armour uid
Pour rappel, voici ce que doit contenir votre rapport (au format txt) :