Этот код должен хешировать пароль с солью. Соль и хешированный пароль сохраняются в базе данных. Самого пароля нет.
Учитывая деликатный характер операции, я хотел убедиться, что все было кошерно.
import hashlib
import base64
import uuid
password = 'test_password'
salt = base64.urlsafe_b64encode(uuid.uuid4().bytes)
t_sha = hashlib.sha512()
t_sha.update(password+salt)
hashed_password = base64.urlsafe_b64encode(t_sha.digest())
t_sha.digest() + salt
. Позже, когда вы расшифруете соленый хэш-пароль, вы можете снова разделить соль, поскольку вы знаете, что декодированный хешированный пароль составляет ровно 32 байта.secrets
вместо этого он ничего не стоит .Ответы:
РЕДАКТИРОВАТЬ: этот ответ неверен. Одна итерация SHA512 выполняется быстро , что делает ее непригодной для использования в качестве функции хеширования паролей. Вместо этого используйте один из других ответов.
Мне нравится. Однако я почти уверен, что вам действительно не нужен base64. Вы могли просто сделать это:
import hashlib, uuid salt = uuid.uuid4().hex hashed_password = hashlib.sha512(password + salt).hexdigest()
Если это не создает трудностей, вы можете получить немного более эффективное хранилище в своей базе данных, сохранив соль и хешированный пароль в виде необработанных байтов, а не шестнадцатеричных строк. Для этого замените
hex
наbytes
иhexdigest
наdigest
.источник
salt
, хранится в базе данных и соленый хешированный пароль тоже.Основываясь на других ответах на этот вопрос, я реализовал новый подход, используя bcrypt.
Зачем использовать bcrypt
Если я правильно понимаю, аргумент использовать
bcrypt
болееSHA512
, чтоbcrypt
предназначено быть медленным.bcrypt
также есть возможность настроить, насколько медленным вы хотите, чтобы он был при генерации хешированного пароля в первый раз:# The '12' is the number that dictates the 'slowness' bcrypt.hashpw(password, bcrypt.gensalt( 12 ))
Медленная работа желательна, потому что если злоумышленник получит в свои руки таблицу, содержащую хешированные пароли, то их будет намного сложнее подобрать.
Реализация
def get_hashed_password(plain_text_password): # Hash a password for the first time # (Using bcrypt, the salt is saved into the hash itself) return bcrypt.hashpw(plain_text_password, bcrypt.gensalt()) def check_password(plain_text_password, hashed_password): # Check hashed password. Using bcrypt, the salt is saved into the hash itself return bcrypt.checkpw(plain_text_password, hashed_password)
Примечания
Мне удалось довольно легко установить библиотеку в системе Linux, используя:
Однако у меня было больше проблем с установкой его в моих системах Windows. Похоже, нужен патч. См. Этот вопрос о переполнении стека: установка py-bcrypt на win 7 64bit python
источник
py-bcrypt
это старый пакет pypi, который с тех пор был переименован вbcrypt
.Разумно не писать криптовалюту самостоятельно, а использовать что-то вроде passlib: https://bitbucket.org/ecollins/passlib/wiki/Home
Легко испортить безопасный код написания криптокода. Противно то, что с некриптографическим кодом вы часто сразу же замечаете, что он не работает, так как ваша программа вылетает. В то время как с криптокодом вы часто узнаете об этом только тогда, когда уже слишком поздно, и ваши данные были скомпрометированы. Поэтому я думаю, что лучше использовать пакет, написанный кем-то другим, кто разбирается в предмете, и который основан на протоколах, протестированных в бою.
Также в passlib есть несколько приятных функций, которые упрощают использование, а также упрощают переход на новый протокол хеширования паролей, если старый протокол оказывается неработоспособным.
Также всего один раунд sha512 более уязвим для атак по словарю. sha512 разработан, чтобы быть быстрым, и на самом деле это плохо при попытке безопасно хранить пароли. Другие люди долго и усердно думали обо всех проблемах такого рода, так что вам лучше воспользоваться этим.
источник
hashlib
предназначен для криптографических хеш-функций.passlib
предназначен для безопасного хранения паролей. Это не одно и то же (хотя многие люди, кажется, так думают ... а потом пароли их пользователей взламываются).passlib
генерирует свою собственную соль, которая хранится в возвращаемой хэш-строке (по крайней мере, для некоторых схем, таких как BCrypt + SHA256 ), поэтому вам не нужно об этом беспокоиться.Чтобы это работало в Python 3, вам необходимо, например, кодировать UTF-8:
hashed_password = hashlib.sha512(password.encode('utf-8') + salt.encode('utf-8')).hexdigest()
В противном случае вы получите:
источник
Начиная с Python 3.4,
hashlib
модуль в стандартной библиотеке содержит функции вывода ключей, которые «предназначены для безопасного хеширования паролей». .Поэтому используйте один из них, например
hashlib.pbkdf2_hmac
, с солью, созданной с использованиемos.urandom
:from typing import Tuple import os import hashlib import hmac def hash_new_password(password: str) -> Tuple[bytes, bytes]: """ Hash the provided password with a randomly-generated salt and return the salt and hash to store in the database. """ salt = os.urandom(16) pw_hash = hashlib.pbkdf2_hmac('sha256', password.encode(), salt, 100000) return salt, pw_hash def is_correct_password(salt: bytes, pw_hash: bytes, password: str) -> bool: """ Given a previously-stored salt and hash, and a password provided by a user trying to log in, check whether the password is correct. """ return hmac.compare_digest( pw_hash, hashlib.pbkdf2_hmac('sha256', password.encode(), salt, 100000) ) # Example usage: salt, pw_hash = hash_new_password('correct horse battery staple') assert is_correct_password(salt, pw_hash, 'correct horse battery staple') assert not is_correct_password(salt, pw_hash, 'Tr0ub4dor&3') assert not is_correct_password(salt, pw_hash, 'rosebud')
Обратите внимание, что:
os.urandom
всегда использует криптографически безопасный источник случайностиhmac.compare_digest
, используемый вis_correct_password
, в основном просто==
оператор для строк, но без возможности короткого замыкания, что делает его невосприимчивым к атакам по времени. Это, вероятно, на самом деле не дает никакого дополнительного значения безопасности , но это тоже не повредит, поэтому я пошел дальше и использовал его.Теорию о том, что делает хороший хэш пароля, и список других функций, подходящих для хеширования паролей, см. На https://security.stackexchange.com/q/211/29805 .
источник
passlib кажется полезным, если вам нужно использовать хэши, хранящиеся в существующей системе. Если у вас есть контроль над форматом, используйте современный хеш, например bcrypt или scrypt. В настоящее время кажется, что bcrypt намного проще использовать из python.
passlib поддерживает bcrypt и рекомендует установить py-bcrypt в качестве бэкэнда: http://pythonhosted.org/passlib/lib/passlib.hash.bcrypt.html
Вы также можете использовать py-bcrypt напрямую, если не хотите устанавливать passlib. В файле readme есть примеры базового использования.
см. также: Как использовать scrypt для генерации хэша для пароля и соли в Python
источник
Я не хочу восстанавливать старую ветку, но ... любой, кто хочет использовать современное безопасное решение, используйте argon2.
https://pypi.python.org/pypi/argon2_cffi
Он выиграл соревнование по хешированию паролей. ( https://password-hashing.net/ ) Его проще использовать, чем bcrypt, и он более безопасен, чем bcrypt.
источник
Сначала импорт: -
import hashlib, uuid
Затем измените свой код в соответствии с этим в своем методе:
uname = request.form["uname"] pwd=request.form["pwd"] salt = hashlib.md5(pwd.encode())
Затем передайте эту соль и uname в запрос sql базы данных, ниже логин - имя таблицы:
sql = "insert into login values ('"+uname+"','"+email+"','"+salt.hexdigest()+"')"
источник