Bcrypt salt 将字节对象视为字符串并且不会散列密码

Bcrypt salt treating byte object as string and wont hash password

已回答

我有一个带有 Postgres 数据库的 Flask 网络应用程序。我正在尝试实施数据库 用 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 table 是如何创建的:

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)


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() 使用密码和盐创建用户 table - 其他问题接踵而至,但我将通过它们进行工作。

user2357112 所示:您正在从数据库中以 str 的形式获取 salt,它需要转换为字节。

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))

OP 回答他自己的问题 - 感谢大家的帮助

将散列作为 varchars 存储在我的数据库中并继续在我的代码中翻转它们是不明智的。相反,我更改了用户 table 以将散列密码和盐存储为 BYTEA 数据类型。

之后,我更改了密码和 salt getter 函数(在 auth.py 中),方法是将 return 类型转换为 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