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

Bcrypt salt treating byte object as string and wont hash password

已回答

我有一个带有Postgres DB的Flask Web应用程序。 我正在尝试实现数据库
用bcrypt进行盐腌,但似乎我的字节表示形式被视为字符串。 需要说明的是:我正在毫无问题地创建哈希密码,但是在授权登录尝试时,使用传递的salt生成比较哈希是行不通的。 这是我尝试登录时发生的错误堆栈:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
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表的创建方式:

1
2
3
4
5
CREATE TABLE users (
    user_pk     SERIAL PRIMARY KEY,
    username    VARCHAR(16) UNIQUE NOT NULL,
    salt        VARCHAR(72) NOT NULL,
    password    VARCHAR(256) NOT NULL

我的登录视图的相关方面

1
2
3
4
5
6
7
8
username = request.form.get('username', None)
password = request.form.get('password', None)

# If user exists...
authorized = helpers.authorize(username, password)

if authorized:
    # login...

这是我创建用户密码和盐的方法

1
2
salt=bcrypt.gensalt(12)
password = bcrypt.hashpw(password.encode('utf-8'), salt)

helpers.py的auth方面

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
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()来创建带有密码和盐的users表-随后出现了其他问题,但我将继续解决这些问题。


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

重现MCVE错误:

1
2
3
4
import bcrypt
salt=str(bcrypt.gensalt())
pw ="Dagg Durneden Co. Mfgrs. Green Hood Shirts"
pw_hash = bcrypt.hashpw(pw.encode('utf-8'), salt)

固定:

1
pw_hash = bcrypt.hashpw(pw.encode('utf-8'), bytes(salt))

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

将哈希作为varchars存储在我的数据库中并继续在我的代码中翻转它们并不明智。 取而代之的是,我更改了users表,以将哈希密码和盐存储为BYTEA数据类型。

之后,我通过将返回类型强制转换为byte()来更改了密码和salt getter函数(在auth.py中)

所以...

1
2
3
4
5
6
7
8
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