回答
我有一个带有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()
创建包含密码和盐的用户表 - 其他问题随之而来,但我会工作通过他们。
答案 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()
所以...
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