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
已回答
我有一个带有 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