【问题标题】:How to retrieve passwords from a database如何从数据库中检索密码
【发布时间】:2017-01-03 18:30:26
【问题描述】:

我正在为我的 Web 应用程序构建一个注册系统,其中用户提供用户名和密码。此数据存储在postgresql 数据库中。我正在使用 bcrypt 生成用户输入密码的加盐哈希,如下所示

import bcrypt
hashed = bcrypt.hashpw(PasswordFromWebForm.encode('UTF-8'), bcrypt.gensalt()) 

这会创建一个看起来像这样的加盐密码 - b'$2b$12$GskbcRCMFHGuXumrNt3FLO'

我将此值存储在postgresql 数据库中。接下来,当用户尝试登录系统时,我想验证他/她的凭据。为此,我打算按照以下方式做一些事情 -

import psycopg2
conn = psycopg2.connect("dbname=test user=me")
cur = conn.cursor()

saltedpassword = cur.execute("SELECT saltedpassword FROM test WHERE loginid = %s", (LoginIDFromWebForm,))

if bcrypt.hashpw(PasswordFromWebForm.encode('UTF-8'), saltedpassword) == saltedpassword:
    print("Success")

这不起作用。它会引发以下TypeError: Unicode-objects must be encoded before hashing 错误。

我怀疑这个错误是因为变量saltedpassword 将值存储为像这样"b'$2b$12$GskbcRCMFHGuXumrNt3FLO'" 这样的字符串,而不是简单的b'$2b$12$GskbcRCMFHGuXumrNt3FLO'(请注意前者中包含加盐密码的引号)

如何解决这个问题?将加盐哈希密码存储在数据库中的最佳方法是什么?在需要验证时如何检索它?为这个相当长的问题道歉 - 请帮忙。

【问题讨论】:

    标签: python postgresql python-3.x psycopg2 bcrypt


    【解决方案1】:

    psycopg2存储Unicode文本,你必须在插入数据库之前解码盐渍密码:

     cur.execute("INSERT INTO test VALUES (%s, %s)",
                 (LoginIDFromWebForm,  saltedpassword.decode('ascii')))
    

    这可以防止插入str() 转换(在数据库中为您提供"b'....'")。

    接下来,当查询saltedpassword不是字符串时,因为cursor.execute()没有返回结果;它返回None

    你需要fetch the result row:

    cur.execute("SELECT saltedpassword FROM test WHERE loginid = %s", (LoginIDFromWebForm,))
    row = cur.fetchone()
    if not row:
        # No such login ID, handle accordingly
    saltedpassword =  row[0].encode('ascii')
    

    由于行包含 Unicode 文本,您需要先编码为字节串,然后再将其传递给 bcrypt。您还想使用bcrypt.checkpw() 函数来检查密码:

    if bcrypt.checkpw(PasswordFromWebForm.encode('UTF-8'), saltedpassword):
        print("Success")
    

    bcrypt.checkpw() 在比较字符串时避免timing attacks,这是您的代码容易受到攻击的东西。

    【讨论】:

    • 公平地说,bcrypt 文档使用if bcrypt.hashpw(password, hashed) == hashed - pypi.python.org/pypi/bcrypt/2.0.0 检查密码
    • @slim:请参阅 bcrypt 3 的更新文档:pypi.python.org/pypi/bcrypt/3.1.2checkpw() 已在 3.1.0 中添加。
    • 啊,是的,刚刚看到:)
    • @MartijnPieters:谢谢,解决了。但我不完全理解为什么我们将 b'$2b$12$GskbcRCMFHGuXumrNt3FLO' 转换为我认为是 Unicode 到 ascii,然后将其存储在数据库中
    • 不,这是一个字节值(b 前缀是一个重要线索)。
    猜你喜欢
    • 2015-12-01
    • 2015-01-28
    • 1970-01-01
    • 1970-01-01
    • 2020-08-21
    • 1970-01-01
    • 1970-01-01
    • 2011-10-13
    • 1970-01-01
    相关资源
    最近更新 更多