Un générateur de mot de passe dans le style d'XKCD

XKCD Langue française

Depuis le début de l'année, j'utilise le gestionnaire de mot de passe open-source Keepass et j'en suis très satisfait.

En général, j'utilise le générateur de mot de passe intégré pour créer des nouveaux mots de passe. Ceux-ci ont le désavantage d'être impossibles à mémoriser.

Peut-on faire mieux ? Je pense que oui, si l'objectif est de générer un mot de passe qui peut être mémorisé facilement.

Comment ? En exploitant l'idée proposée dans le XKCD ci-dessous et en l'adaptant à la langue française !

In [1]:
from IPython.display import Image

Image(url='https://imgs.xkcd.com/comics/password_strength.png')
Out[1]:

Mots français

Pour commencer, il nous faut une liste de mots de la langue française, que l'on peut trouver ici : http://www.pallier.org/liste-de-mots-francais.html

Avec pandas, nous pouvons facilement télécharger la liste de mot et la transformer en DataFrame.

In [2]:
import pandas as pd

df = pd.read_csv('http://www.pallier.org/extra/liste.de.mots.francais.frgut.txt', header=None)

df.head()
Out[2]:
0
0 a
1 à
2 abaissa
3 abaissable
4 abaissables

Une liste de mot aléatoire

Maintenant, nous pouvons mettre en oeuvre un algorithme de génération : tirer quatre mots au hasard et les assembler.

In [3]:
from numpy.random import choice

def make_password(df, n=4):
    """Generates a password by randomly selecting n words from the dataframe."""
    indices = choice(df.index, size=4, replace=True)
    return [item[0] for item in df.loc[indices].values.tolist()]

make_password(df)
Out[3]:
['limettiers', 'ressentirions', 'prédisposée', 'désolidarisassions']

On peut également calculer l'entropie du mot de passe ainsi proposé (voir ici : https://crypto.stackexchange.com/questions/374/how-should-i-calculate-the-entropy-of-a-password) :

In [4]:
from numpy import log2

def compute_entropy_bits(df, n=4):
    """Returns bits of entropy computed using: 4 * log_2(n) 
    where n is the length of the list we're choosing words from."""
    return n * log2(df.size)

compute_entropy_bits(df, n=4), compute_entropy_bits(df, n=5), compute_entropy_bits(df, n=10)
Out[4]:
(73.4415195246536, 91.801899405817, 183.603798811634)

Et pourquoi pas une petite IHM ?

Finalement, on peut faire une petite IHM pour pour facilement générer un mot de passe de quatre mots.

In [5]:
from ipywidgets import Button, HBox, VBox, HTML

class GUI:
    def __init__(self):
        self.buttons = [Button(description='autre mot {}'.format(i)) for i in range(1, 5)]
        self.reset = Button(description='nouveau')
        self.passwordbox = HTML(description='mot de passe')
        self.create_new_word()
        
        def on_new_click(b):
            self.create_new_word()        
        self.reset.on_click(on_new_click)
        
        def on_word_click(b):
            pos = [b.description for b in self.buttons].index(b.description)
            self.change_word(pos=pos)
        for button in self.buttons:
            button.on_click(on_word_click)
            
    def show(self):
        return VBox([HBox(self.buttons + [self.reset]),
                     self.passwordbox])
    
    def create_new_word(self):
        self.words = make_password(df)
        self.passwordbox.value = "{} {} {} {}".format(*self.words)
        
    
    def change_word(self, pos=0):
        self.words[pos] = make_password(df)[pos]
        self.passwordbox.value = "{} {} {} {}".format(*self.words)

gui = GUI()
gui.show()

Et voilà, un petit outil simple qui permet de générer des mots de passe personnalisés !

Comments