web-dev-qa-db-fra.com

La méthode la plus sûre de Python pour stocker et récupérer les mots de passe d'une base de données

Vous souhaitez stocker les noms d'utilisateur et les mots de passe dans une base de données, et je me demande quel est le moyen le plus sûr de le faire. Je sais que je dois utiliser un sel quelque part, mais je ne sais pas comment le générer de manière sécurisée ni comment l’appliquer pour chiffrer le mot de passe. Quelques exemples de code Python seraient grandement appréciés. Merci.

31
ensnare

Stockez le mot de passe + sel sous forme de hachage et le sel. Regardez comment Django le fait: docs de base et source . Dans la base de données, ils stockent <type of hash>$<salt>$<hash> dans un seul champ de caractères. Vous pouvez également stocker les trois parties dans des champs distincts.

La fonction pour définir le mot de passe:

def set_password(self, raw_password):
    import random
    algo = 'sha1'
    salt = get_hexdigest(algo, str(random.random()), str(random.random()))[:5]
    hsh = get_hexdigest(algo, salt, raw_password)
    self.password = '%s$%s$%s' % (algo, salt, hsh)

Le get_hexdigest est juste une mince enveloppe autour de certains algorithmes de hachage. Vous pouvez utiliser hashlib pour cela. Quelque chose comme hashlib.sha1('%s%s' % (salt, hash)).hexdigest()

Et la fonction pour vérifier le mot de passe:

def check_password(raw_password, enc_password):
    """
    Returns a boolean of whether the raw_password was correct. Handles
    encryption formats behind the scenes.
    """
    algo, salt, hsh = enc_password.split('$')
    return hsh == get_hexdigest(algo, salt, raw_password)
37
rz.

Je pense qu'il est préférable d'utiliser un paquet dédié au hachage des mots de passe pour cela comme passlib: http://packages.python.org/passlib/ pour des raisons que j'ai expliquées ici: https://stackoverflow.com/a/10948614/893857

14
M.D.

J'ai répondu à ceci ici: https://stackoverflow.com/a/18488878/1661689 , ainsi que @Koffie.

Je ne sais pas comment souligner assez que la réponse acceptée n'est PAS sécurisée. Il vaut mieux que le texte brut et mieux qu’un hachage non salé, mais il reste toujours extrêmement vulnérable attaqué par un dictionnaire et même par la force. S'il vous plait, utilisez utilisez un fichier KDF SLOW comme bcrypt (ou au moins PBKDF2 avec 10 000 itérations)

12
Terrel Shumway

Si vous maîtrisez suffisamment les deux extrémités de l'application, le meilleur moyen consiste à utiliser PAK-Z + .

(Modifié: la version d'origine recommandée SRP mais PAK-Z + dispose d'une preuve de sécurité.)

3
Paul Crowley

Voici un moyen plus simple (tiré d’effbot), à condition que les mots de passe d’une longueur supérieure à 8 ne posent aucun problème *:

import crypt

import random, string

def getsalt(chars = string.letters + string.digits):
    # generate a random 2-character 'salt'
    return random.choice(chars) + random.choice(chars)

pour générer le mot de passe:

crypt.crypt("password", getsalt())

*: Un mot de passe d'une longueur supérieure à 8 est supprimé de la droite à 8 caractères

0
llazzaro