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

时间:2017-03-29 18:56:00

标签: python postgresql flask bcrypt salt

回答

我有一个带有Postgres数据库的Flask Web应用程序。我正在尝试实现数据库 用bcrypt进行盐析,但似乎我的字节表示被视为一个字符串。要明确:我正在创建散列密码没有问题,但是在授权登录尝试时,使用传递的salt生成比较散列不起作用。这是我尝试登录时出现的错误堆栈:

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)


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 个答案:

答案 0 :(得分:1)

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

答案 1 :(得分:0)

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

将哈希值存储为数据库中的varchars并继续在我的代码中翻转它们并不聪明。相反,我更改了users表以将散列密码和salt存储为BYTEA数据类型。

之后,我通过将返回类型转换为byte()

来更改我的密码和salt getter函数(在auth.py中)

所以...

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