检查加密密码时出现类似字节的对象错误(Python)

问题描述 投票:0回答:1

我正在创建一个需要用户登录的应用程序。用户名和密码必须存储在数据库中,但我不想将它们存储为平面文本。我按照 this 教程了解如何在数据库中安全地存储密码。我正在使用教程中的代码,除了我做了一些更改以使用 pyodbc 而不是他们的 SQL 库。

要创建用户名和密码,我使用此代码,该代码效果很好并发布到数据库:

import pyodbc
import os
import hashlib
  
PEPPER = "SECRET_KEY" 

def create_user(username, password):
    
    conn = pyodbc.connect(
            r"Driver={Microsoft Access Driver (*.mdb, *.accdb)};DBQ=" + db_path + ";"
        ) 

    cursor = conn.cursor()
   
    # Generate secure hash
    password_hash = create_secure_password(password)  

    # Split hash into components
    salt, key = password_hash[:16], password_hash[16:]
    hash_algo = "sha256"
    iterations = 100_000

    # Insert into database
    info = (username, key, salt, hash_algo, iterations)
    cursor.execute("INSERT INTO Login_Info ([username], [password_hash], [salt], [hash_algo], [iterations] ) VALUES (?, ?, ?, ?, ?)", info)

    conn.commit()
    conn.close()

def create_secure_password(password):
  salt = os.urandom(16)  
  iterations = 100_000
  hash_value = hashlib.pbkdf2_hmac('sha256',password.encode('utf-8') + PEPPER.encode('utf-8'),  salt, iterations)  
  password_hash = salt + hash_value
  return password_hash 

数据库条目显示如下: 数据库中的用户名和密码

但是,当我使用该方法根据数据库检查用户名和密码时,出现以下错误:

TypeError: a bytes-like object is required, not 'str'

错误在于这行代码,我相信它将输入的密码转换为哈希值以与数据库哈希值进行比较

password_hash = hashlib.pbkdf2_hmac(hash_algo, password.encode('utf-8'), salt, iterations)

登录方法完整代码如下:

def login(username, password):
    #connect to DB
    conn = pyodbc.connect(
            r"Driver={Microsoft Access Driver (*.mdb, *.accdb)};DBQ=" + db_path + ";"
        ) 

    cursor = conn.cursor()
 
    # Define your SQL query
    select_sql = "SELECT * FROM Login_Info WHERE username = ?"

    # Execute the query using the cursor
    cursor.execute(select_sql, (username,))

    # Fetch one row of result
    account = cursor.fetchone()


    if not account:
        print("Invalid username")
        return
 
    salt, db_key, hash_algo, iterations = account[2:6]



    # Recompute hash from user entered password
    password_hash = hashlib.pbkdf2_hmac(hash_algo, password.encode('utf-8'), salt, iterations)
 
    # Compare hashes
    if password_hash == db_key:
        print("Login successful")
    else:
        print("Invalid password")

我尝试过在网上寻找其他资源,但找不到遇到这个问题的人

python database passwords hashlib
1个回答
0
投票

我不相信作为

bytes
对象插入的数据会作为
bytes
对象检索,但我没有您的数据库。 一种解决方案是存储从
str
方法获得的
bytes.hex()
对象,并在从数据库中提取后将其转换回
bytes
对象。

重新计算的哈希值中也缺少

+ PEPPER

下面是一个经过验证的最小示例,它删除了数据库并使用字符串:

import os
import hashlib

PEPPER = b'SECRET_KEY'  # bytes object so no need to .encode()

def create_user(username, password):
    salt, key = create_secure_password(password)
    hash_algo = 'sha256'
    iterations = 100_000

    # Insert these items into database.
    return username, key, salt, hash_algo, iterations

def create_secure_password(password):
    salt = os.urandom(16)
    iterations = 100_000
    hash_value = hashlib.pbkdf2_hmac('sha256',password.encode() + PEPPER,  salt, iterations)
    return salt.hex(), hash_value.hex()  # Use hex strings, not bytes objects

def login(username, password):

    # Simulate data retrieved from database
    _, db_key, salt, hash_algo, iterations = create_user(username, password)

    # Recompute hash from user entered password.
    # Convert salt to bytes, then the hash to hex.
    # Added missing PEPPER.
    password_hash = hashlib.pbkdf2_hmac(hash_algo, password.encode() + PEPPER, bytes.fromhex(salt), iterations).hex()
 
    # Compare hashes as strings.
    if password_hash == db_key:
        print('Login successful')
    else:
        print('Invalid password')

login('mark', 'abc')

输出:

Login successful
© www.soinside.com 2019 - 2024. All rights reserved.