Осуществляется лечение солью Byte объект как строку, а не хэш пароля
ответил
У меня есть веб-приложение Flask с базой данных Postgres. Я пытаюсь реализовать базу данных соление с помощью bcrypt, но кажется, что мое байтовое представление рассматривается как строка. Для ясности: я создаю хэшированный пароль без проблем, но при авторизации попытки входа в систему, генерация хэша сравнения с переданной солью не работает. Вот стек ошибок, который возникает при попытке входа в систему:
lost/app/views/login.py", line 37, in login
authorized = helpers.authorize(username, password)
lost/app/helpers.py", line 108, in authorize
return _check_hash_for_user(username, password)
lost/app/helpers.py", line 93, in _check_hash_for_user
generated_hash = _recreate_hash(password, _get_salt_for_user(username))
lost/app/helpers.py", line 100, in _recreate_hash
hash_pass = bcrypt.hashpw(password.encode('utf-8'), salt)
lost/venv/lib/python3.6/site-packages/bcrypt/__init__.py", line 62, in hashpw
raise TypeError("Unicode-objects must be encoded before hashing")
Как выглядит моя таблица users
создано:
CREATE TABLE users (
user_pk SERIAL PRIMARY KEY,
username VARCHAR(16) UNIQUE NOT NULL,
salt VARCHAR(72) NOT NULL,
password VARCHAR(256) NOT NULL
соответствующие аспекты моего представления логина
username = request.form.get('username', None)
password = request.form.get('password', None)
# If user exists...
authorized = helpers.authorize(username, password)
if authorized:
# login...
Вот как я создал пароль пользователя и соль
salt = bcrypt.gensalt(12)
password = bcrypt.hashpw(password.encode('utf-8'), salt)
аспект auth helpers.py
def _get_hash_for_user(username):
password = db_query("SELECT password FROM users WHERE username=%s;", [username])[0][0]
return password
def _get_salt_for_user(username):
salt = db_query("SELECT salt FROM users WHERE username=%s;", [username])[0][0]
return salt
def _create_password_hash(password):
salt = bcrypt.gensalt(16)
hashed_pass = bcrypt.hashpw(password, salt)
return hashed_pass, salt
def _check_hash_for_user(username, password):
stored_hash = _get_hash_for_user(username)
generated_hash = _recreate_hash(password, _get_salt_for_user(username))
return stored_hash == generated_hash
def _recreate_hash(password, salt):
hash_pass = bcrypt.hashpw(password.encode('utf-8'), salt)
return hash_pass
def authorize(username, password):
return _check_hash_for_user(username, password)
Редактировать:
По просьбе кого-то, кто пытается помочь мне решить эту проблему, я теперь создаю таблицу пользователей с паролем и солью, используя тип данных BYTEA
вместо VARCHAR()
- возникли другие проблемы, но я буду работать через их.
2 ответа:
Как указано в
user2357112
: Вы получаете свою соль из базы данных какstr
, и ее нужно привести к байтам.MCVE для воспроизведения ошибки:
import bcrypt salt = str(bcrypt.gensalt()) pw = "Dagg Durneden Co. Mfgrs. Green Hood Shirts" pw_hash = bcrypt.hashpw(pw.encode('utf-8'), salt)
Исправить:
pw_hash = bcrypt.hashpw(pw.encode('utf-8'), bytes(salt))
ОП отвечает на свой собственный вопрос-спасибо всем за помощь
Было неразумно хранить хэши в виде варчаров в моей базе данных и продолжать листать их в моем коде. Вместо этого я изменил таблицу users, чтобы хранить хэшированный пароль и соль как типы данных BYTEA.После этого я изменил свой пароль и функции Salt getter (in auth.py) путем приведения возвращаемого типа как
byte()
Итак...
def _get_hash_for_user(username): password = byte(db_query("SELECT password FROM users WHERE username=%s;", [username])[0][0]) return password def _get_salt_for_user(username): salt = byte(db_query("SELECT salt FROM users WHERE username=%s;", [username])[0][0]) return salt