Осуществляется лечение солью 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 2

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