Ce cours est visible gratuitement en ligne.

Ce cours existe en livre papier.

Ce cours existe en eBook.

Vous pouvez obtenir un certificat de réussite à l'issue de ce cours.

J'ai tout compris !
Apprenez à programmer en Python

Apprenez à programmer en Python

Mis à jour le lundi 8 septembre 2014
  • 4 semaines
  • Facile

Dans ce chapitre, nous allons nous intéresser aux mots de passe et à la façon de les gérer en Python, c'est-à-dire de les réceptionner et de les protéger.

Nous allons découvrir deux modules dans ce chapitre : d'abord getpass qui permet de demander un mot de passe à l'utilisateur, puis hashlib qui permet de chiffrer le mot de passe réceptionné.

Réceptionner un mot de passe saisi par l'utilisateur

Vous allez me dire, j'en suis sûr, qu'on a déjà une façon de réceptionner une saisie de l'utilisateur. Cette méthode, on l'a vue assez tôt dans le cours : il s'agit naturellement de la fonction input.

Mais input n'est pas très discrète. Si vous saisissez un mot de passe confidentiel, il apparaît de manière visible à l'écran, ce qui n'est pas toujours souhaitable. Quand on tape un mot de passe, c'est même rarement souhaité !

C'est ici qu'intervient le module getpass. La fonction qui nous intéresse porte le même nom que le module. Elle va réagir comme input, attendre une saisie de l'utilisateur et la renvoyer. Mais à la différence d'input, elle ne va pas afficher ce que l'utilisateur saisit.

Faisons un essai :

>>> from getpass import getpass
>>> mot_de_passe = getpass()
Password:
>>> mot_de_passe
'un mot de passe'
>>>

Comme vous le voyez… bah justement on ne voit rien ! Le mot de passe que l'on tape est invisible. Vous appuyez sur les touches de votre clavier mais rien ne s'affiche. Cependant, vous écrivez bel et bien et, quand vous appuyez sur Entrée, la fonction getpass renvoie ce que vous avez saisi.

Ici, on le stocke dans la variable mot_de_passe. C'est plus discret qu'input, reconnaissez-le !

Bon, il reste un détail, mineur certes, mais un détail quand même : le prompt par défaut, c'est-à-dire le message qui vous invite à saisir votre mot de passe, est en anglais. Heureusement, il s'agit tout simplement d'un paramètre facultatif de la fonction :

>>> mot_de_passe = getpass("Tapez votre mot de passe : ")
Tapez votre mot de passe : 
>>>

C'est mieux.

Bien entendu, tous les mots de passe que vous réceptionnerez ne viendront pas forcément d'une saisie directe d'un utilisateur. Mais, dans ce cas précis, la fonction getpass est bien utile. À la fin de ce chapitre, nous verrons une utilisation complète de cette fonction, incluant réception et chiffrement de notre mot de passe en prime, deux en un.

Chiffrer un mot de passe

Cette fois-ci, nous allons nous intéresser au module hashlib. Mais avant de vous montrer comment il fonctionne, quelques explications s'imposent.

Chiffrer un mot de passe ?

La première question qu'on pourrait légitimement se poser est « pourquoi protéger un mot de passe ? ». Je suis sûr que vous pouvez trouver par vous-mêmes pas mal de réponses : il est un peu trop facile de récupérer un mot de passe s'il est stocké ou transmis en clair. Et, avec un mot de passe, on peut avoir accès à beaucoup de choses : je n'ai pas besoin de vous l'expliquer. Cela fait que généralement, quand on a besoin de stocker un mot de passe ou de le transmettre, on le chiffre.

Maintenant, qu'est-ce que le chiffrement ? A priori, l'idée est assez simple : en partant d'un mot de passe, n'importe lequel, on arrive à une seconde chaîne de caractères, complètement incompréhensible.

Quel intérêt ?

Eh bien, si vous voyez passer, devant vos yeux, une chaîne de caractères comme b47ea832576a75814e13351dcc97eaa985b9c6b7, vous ne pouvez pas vraiment deviner le mot de passe qui se cache derrière.

Et l'ordinateur ne peut pas le déchiffrer si facilement que cela non plus. Bien sûr, il existe des méthodes pour déchiffrer un mot de passe mais nous ne les verrons certainement pas ici. Nous, ce que nous voulons savoir, c'est comment protéger nos mots de passe, pas comment déchiffrer ceux des autres !

Comment fonctionne le chiffrement ?

Grave question. D'abord, il existe plusieurs techniques ou algorithmes de chiffrement. Chiffrer un mot de passe avec un certain algorithme ne donne pas le même résultat qu'avec un autre algorithme.

Ensuite, l'algorithme, quel qu'il soit, est assez complexe. Je serais bien incapable de vous expliquer en détail comment cela marche, on fait appel à beaucoup de concepts mathématiques relativement poussés.

Mais si vous voulez faire un exercice, je vous propose quelque chose d'amusant qui vous donnera une meilleure idée du chiffrement.

Commencez par numéroter toutes les lettres de l'alphabet (de a à z) de 1 à 26. Représentez l'ensemble des valeurs dans un tableau, ce sera plus simple.

A (1)

B (2)

C (3)

D (4)

E (5)

F (6) &

G (7)

H (8)

I (9)

J (10)

K (11)

L (12)

M (13)

N (14)

O (15)

P (16)

Q (17)

R (18)

S (19) &

T (20)

U (21)

V (22)

W (23)

X (24)

Y (25)

Z (26)

Maintenant, supposons que nous allons chercher à chiffrer des prénoms. Pour cela, nous allons baser notre exemple sur un calcul simple : dans le tableau ci-dessus, prenez la valeur numérique de chaque lettre constituant le prénom et additionnez l'ensemble des valeurs obtenues.

Par exemple, partons du prénom Eric. Quatre lettres, cela ira vite. Oubliez les accents, les majuscules et minuscules. On a un E (5), un R (18), un I (9) et un C (3). En ajoutant les valeurs de chaque lettre, on a donc 5 + 18 + 9 + 3, ce qui donne 35.

Conclusion : en chiffrant Eric grâce à notre algorithme, on obtient le nombre 35.

C'est l'idée derrière le chiffrement même si, en réalité, les choses sont beaucoup plus complexes. En outre, au lieu d'avoir un chiffre en sortie, on a généralement plutôt une chaîne de caractères.

Mais prenez cet exemple pour vous amuser, si vous voulez. Appliquez notre algorithme à plusieurs prénoms. Si vous vous sentez d'attaque, essayez de faire une fonction Python qui prenne en paramètre notre chaîne et renvoie un chiffre, ce n'est pas bien difficile.

Vous pouvez maintenant vous rendre compte que derrière un nombre tel que 35, il est plutôt difficile de deviner que se cache le prénom Eric !

Si vous faites le test sur les prénoms Louis et Jacques, vous vous rendrez compte… qu'ils produisent le même résultat, 76. En effet :

  • Louis = 12 + 15 + 21 + 9 + 19 = 76

  • Jacques = 10 + 1 + 3 + 17 + 21 + 5 + 19 = 76

C'est ce qu'on appelle une collision : en prenant deux chaînes différentes, on obtient le même chiffrement au final.

Les algorithmes que nous allons voir dans le module hashlib essayent de minimiser, autant que possible, les collisions. Celui que nous venons juste de voir en est plein : il suffit de changer de place les lettres de notre prénom et nous retombons sur le même nombre, après tout.

Voilà. Fin de l'exercice, on va se pencher sur le module hashlib maintenant.

Chiffrer un mot de passe

On peut commencer par importer le module hashlib :

import hashlib

On va maintenant choisir un algorithme. Pour nous aider dans notre choix, le module hashlib nous propose deux listes :

  • algorithms_guaranteed : les algorithmes garantis par Python, les mêmes d'une plateforme à l'autre. Si vous voulez faire des programmes portables, il est préférable d'utiliser un de ces algorithmes :

>>> hashlib.algorithms_guaranteed
{'sha1', 'sha224', 'sha384', 'sha256', 'sha512', 'md5'}
>>>
  • algorithms_available : les algorithmes disponibles sur votre plateforme. Tous les algorithmes garantis s'y trouvent, plus quelques autres propres à votre système.

Dans ce chapitre, nous allons nous intéresser à sha1.

Pour commencer, nous allons créer notre objet SHA1. On va utiliser le constructeur sha1 du module hashlib. Il prend en paramètre une chaîne, mais une chaîne de bytes (octets).

Pour obtenir une chaîne de bytes depuis une chaîne str, on peut utiliser la méthode encode. Je ne vais pas rentrer dans le détail des encodages ici. Pour écrire directement une chaîne bytes sans passer par une chaîne str, vous avez une autre possibilité consistant à mettre un b minuscule avant l'ouverture de votre chaîne :

>>> b'test'
b'test'
>>>

Générons notre mot de passe :

>>> mot_de_passe = hashlib.sha1(b"mot de passe")
>>> mot_de_passe
<sha1 HASH object @ 0x00BF0ED0>
>>>

Pour obtenir le chiffrement associé à cet objet, on a deux possibilités :

  • la méthode digest, qui renvoie un type bytes contenant notre mot de passe chiffré ;

  • la méthode hexdigest, qui renvoie une chaîne str contenant une suite de symboles hexadécimaux (de 0 à 9 et de A à F).

C'est cette dernière méthode que je vais montrer ici, parce qu'elle est préférable pour un stockage en fichier si les fichiers doivent transiter d'une plateforme à l'autre.

>>> mot_de_passe.hexdigest()
'b47ea832576a75814e13351dcc97eaa985b9c6b7'
>>>

Et pour déchiffrer ce mot de passe ?

On ne le déchiffre pas. Si vous voulez savoir si le mot de passe saisi par l'utilisateur correspond au chiffrement que vous avez conservé, chiffrez le mot de passe qui vient d'être saisi et comparez les deux chiffrements obtenus :

import hashlib
from getpass import getpass

chaine_mot_de_passe = b"azerty"
mot_de_passe_chiffre = hashlib.sha1(chaine_mot_de_passe).hexdigest()

verrouille = True
while verrouille:
    entre = getpass("Tapez le mot de passe : ") # azerty
    # On encode la saisie pour avoir un type bytes
    entre = entre.encode()
    
    entre_chiffre = hashlib.sha1(entre).hexdigest()
    if entre_chiffre == mot_de_passe_chiffre:
        verrouille = False
    else:
        print("Mot de passe incorrect")

print("Mot de passe accepté...")

Cela me semble assez clair. Nous avons utilisé l'algorithme sha1, il en existe d'autres comme vous pouvez le voir dans hashlib.algorithms_available.

Je m'arrête pour ma part ici ; si vous voulez aller plus loin, je vous redirige vers la documentation de Python sur les modules getpass et hashlib.

En résumé

  • Pour demander à l'utilisateur de saisir un mot de passe, on peut utiliser le module getpass.

  • La fonction getpass du module getpass fonctionne de la même façon que input, sauf qu'elle n'affiche pas ce que l'utilisateur saisit.

  • Pour chiffrer un mot de passe, on va utiliser le module hashlib.

  • Ce module contient en attributs les différents algorithmes pouvant être utilisés pour chiffrer nos mots de passe.

Découvrez aussi ce cours en...

Exemple de certificat de réussite
Exemple de certificat de réussite