Самый безопасный метод Python для хранения и извлечения паролей из базы данных - PullRequest
31 голосов
/ 03 апреля 2010

Нужно хранить имена пользователей и пароли в базе данных, и мне интересно, какой самый безопасный способ сделать это. Я знаю, что где-то должен использовать соль, но не уверен, как ее сгенерировать безопасно или как применить ее для шифрования пароля. Некоторые примеры кода Python будут с благодарностью. Спасибо.

Ответы [ 5 ]

38 голосов
/ 03 апреля 2010

Храните пароль + соль как хеш и соль. Посмотрите, как это делает Django: базовые документы и source . В БД они хранят <type of hash>$<salt>$<hash> в одном поле char. Вы также можете хранить три части в отдельных полях.

Функция для установки пароля:

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)

get_hexdigest - это просто оболочка для некоторых алгоритмов хеширования. Вы можете использовать hashlib для этого. Что-то вроде hashlib.sha1('%s%s' % (salt, hash)).hexdigest()

И функция проверки пароля:

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)
14 голосов
/ 08 июня 2012

Я думаю, что для этого лучше всего использовать пакет, предназначенный для хеширования паролей, такой как passlib: http://packages.python.org/passlib/ по причинам, которые я объяснил здесь: https://stackoverflow.com/a/10948614/893857

13 голосов
/ 28 августа 2013

Я ответил здесь: https://stackoverflow.com/a/18488878/1661689,, как и @ Koffie.

Я не знаю, как подчеркнуть, что принятый ответ НЕ является безопасным. Это лучше, чем простой текст, и лучше, чем несоленый хеш, но он все еще чрезвычайно уязвим к словарным атакам и даже атакам методом "грубой силы". Вместо этого, пожалуйста, используйте МЕДЛЕННЫЙ KDF , такой как bcrypt (или как минимум PBKDF2 с 10000 итераций)

3 голосов
/ 07 апреля 2010

Если у вас достаточно контроля над обоими конечными точками приложения, то лучший способ - использовать PAK-Z + .

(Отредактировано: рекомендуется оригинальная версия SRP , но PAK-Z + имеет подтверждение безопасности.)

0 голосов
/ 05 января 2013

Вот более простой способ (взят из effbot), при условии, что пароли длиной более 8 не будут проблемой *:

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)

для генерации пароля:

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

*: пароль длиной более 8 извлекается справа вниз до 8 символов

...