Partage
  • Partager sur Facebook
  • Partager sur Twitter

Algorithme : générateur / testeur de mot de passe

Anonyme
13 juillet 2010 à 9:23:36

Bonjour tout le monde,

j'ai quelques petites questions pour vous concernant des algos que j'ai rapidement (ce n'était sans doute pas à préciser :p) faits.
J'ai une fonction pour générer un mot de passe, et une autre pour vérifier un mot de passe que l'on entre.

Pour le générateur, au delà de 10 000 000 de caractères, cela devient long, plus d'une minute 20 secondes environ 45 secondes (édition à 14h30). Je me demande comment l'optimiser ? Faudrait-il générer les caractères par groupe de plusieurs (en fonction du nombre de caractère demandés) ou bien revoir entièrement la génération ? Avis aux experts, je suis ouvert à toute piste pour accélérer tout ça :)

Enfin, pour le vérificateur, outre le fait qu'il manque un dictionnaire, j'ai l'impression que le testeur n'est pas bon. Par exemple je ne vérifie pas les répétitions (je ne vois pas trop comment faire pour le moment), mais aussi autre chose ... mais quoi ?

Car pour un mot de passe du style cz8+u-Sb+22oV01*hgQJE0)80B4h.xF7rAo0x0YS0ET6INao)b+k&heS8YO7A722-EB6!a.bN8v2b$Gzg&5c2r)2*(%xkaHKe'aSK5L7(k,,u3+2&g+V,!5%*2mY3BR1hvC0-C(9X79gxY(KD-n le résultat est "Mot de passe moyen", alors qu'il devrait plutôt être "Mot de passe fort".

Avez-vous des idées sur la question ?

Je vous met le code ci dessous (en secret pour ne pas prendre trop de place):
#!/usr/bin/env python
# -*- coding: UTF-8 -*-

"""
Petit script pour générer / vérifier un mot de passe
"""

# --------
# Imports
# --------
from random import randint
import string

# --------
# Fonctions
# --------
def generateurMotAlea( nbChrs=8 ):
    """
    Fonction concaténant les caractères générés par la fonction genererChr
    Param : le nbre de caractères à générer - par défaut : 8
    """
    i = 0
    chaineMot = ''
    while i < nbChrs:
        chaineMot += chr( randint(33, 126) ) #un caractère ascii
        i += 1

    print '----------Mot de passe----------'
    print chaineMot


def verificateurMdp( mdp ):
    """
    Vérifie la complexité du mot de passe passé en paramètre
    ----
    rem : pour une excellente vérification,
    il faudrait ajouter un (ou des) dico(s) de mots/noms courants
    """
    chrsNormaux = string.ascii_letters+string.digits
    nbChrsAnormaux = 0
    nbChrsNormaux = 0
    ptsComplexite = 0
    nbMin = 0
    nbMaj = 0
    nbNbrs = 0

    for letter in mdp:
        #comprer les chrs qui ne sont ni lettre, ni chiffre
        if( letter not in chrsNormaux ):
            nbChrsAnormaux += 1
        else: #c'est une lettre ou un chiffre
            nbChrsNormaux += 1
        #compter le nb de maj
        if( 65 <= ord(letter) <= 90 ):
            nbMaj += 1
        #compter le nb de min
        if( 97 <= ord(letter) <= 122 ):
            nbMin += 1
        #compter les nbrs
        if( 48 <= ord(letter) <= 57 ):
            nbNbrs += 1

    #compter les pts du mot de passe
    if( len(mdp) > 5) :
        ptsComplexite += 1
    if( nbChrsAnormaux >= 2 ):
        ptsComplexite += 1
    if( nbChrsAnormaux >= nbChrsNormaux ):
        ptsComplexite += 1
    if( nbMaj >= 2 and nbMin >= 2 and nbNbrs >= 2 ):
        ptsComplexite += 1

    #actuellement, aucun mot de passe ne peut être réellement fort
    #car il me manque des choses à vérifier
    #comme vérifier si le mot de passe (ou un bout) est dans un dico ou non
    #(et là changer la limite de "fort" à 5 ??)
    if( ptsComplexite < 1 ):
        return 'Mot de passe faible'
    elif( ptsComplexite < 4 ):
        return 'Mot de passe moyen'
    else:
        return 'Mot de passe fort'


def saisieOption():
    """
    Petit menu pour choisir quoi faire
    Return : int - le choix fait
    -----
    Rem : pas de vérification de l'input (pas le but recherché actuellement)
    """
    print 'Quelle operation ?'
    print '1 - Generer mot de passe'
    print '2 - Verifier un mot de passe'
    print
    print 'Autre - Quitter'
    print

    return input('Votre choix: ')


def saisieLenMot():
    """
    Fonction pour saisir la longueur du mot de passe à générer
    -----
    Rem : pas de vérification de l'input (pas le but recherché actuellement)
    """
    print 'Quelle longueur a generer ?'
    print
    return input('Longueur voulue: ')

def saisieMdp():
    """
    Fonction pour saisir le mot de passe à tester
    -----
    Rem : pas de vérification de l'input (pas le but recherché actuellement)
    """
    print 'Entrez le mdp a tester'
    print
    return raw_input('Mot de passe: ')


def main( ver ):
    """
    Fonction principale de l'appli
    """
    print 'PsswdTester - version ' + ver
    print

    optn = saisieOption()

    if( optn == 1 ):
        lenMot = saisieLenMot()
        generateurMotAlea( lenMot )
    elif( optn == 2 ):
        mot = saisieMdp()
        print 'Resultat: ' + verificateurMdp( mot )
    else:
        exit(0)

# --------
# Appli
# --------
if __name__ == '__main__':
    main('0.1')


Merci d'avance pour vos pistes et vos indices d'amélioration.
Bonne journée :)

Edit 10:55 : Petite mise à jour du code & précision pour le vérificateur de mot de passe

Edit 14:30 : Changement du code, voir ligne surlignée (numéro 25) et suppression de la fonction genererChr. Du coup plus qu'un seul randint() par itération, au lieu de 2.
  • Partager sur Facebook
  • Partager sur Twitter
22 avril 2011 à 0:37:23

Bonsoir, pour generateurMotAlea tu devrait utiliser une itération (range) ou une compréhesion de liste.
def generateurMotAlea( nbChrs=8 ):
 print '----------Mot de passe----------'
 print [randint(33, 126) for _ in range(nbChrs)]


Attention les prints c'est lent.
  • Partager sur Facebook
  • Partager sur Twitter
22 avril 2011 à 17:37:08

T'as vraiment besoin de générer des mots de passe de 10000 caractères ? Indépendamment de l'algorithmique derrière, il faut aussi penser à leur utilité. Selon le système pour lequel tu vas l'employer, ça peut même diminuer beaucoup la sécurité.
  • Partager sur Facebook
  • Partager sur Twitter
22 avril 2011 à 22:22:23

Citation

Par exemple je ne vérifie pas les répétitions (je ne vois pas trop comment faire pour le moment), mais aussi autre chose ... mais quoi ?



Tu veux générer un mot de passe qui n'est pas prédictible? Dans ce cas n'utilise pas random. Ce n'est pas un PRNG cryptographique.

Je te suggère d'utiliser /dev/random si tu veux un programme sous linux. (man random) Ce sera très lent vu qu'il faudra le tmeps de générer de l'entropie blabla.
  • Partager sur Facebook
  • Partager sur Twitter
23 avril 2011 à 12:40:06

@cpuid: et /dev/urandom ?
  • Partager sur Facebook
  • Partager sur Twitter
yjltg.
23 avril 2011 à 16:05:34

http://linux.die.net/man/4/random

Citation

A read from the /dev/urandom device will not block waiting for more entropy. As a result, if there is not sufficient entropy in the entropy pool, the returned values are theoretically vulnerable to a cryptographic attack on the algorithms used by the driver. Knowledge of how to do this is not available in the current non-classified literature, but it is theoretically possible that such an attack may exist. If this is a concern in your application, use /dev/random instead.



Après faut voir ce qu'il cherche. Je doute qu'il ait vraiment besoin d'un truc comme ca mais bon. :)

  • Partager sur Facebook
  • Partager sur Twitter
17 août 2014 à 17:25:18

Est-il possible de créer un algorithme de génération de mot de passe sur algobox

  • Partager sur Facebook
  • Partager sur Twitter