【发布时间】:2020-10-26 00:03:17
【问题描述】:
我目前正在构建一个密码管理器作为一个项目,以更好地了解 PostgreSQL,同时学习如何处理 Python 和数据库之间的数据。
这里有一点关于我的密码管理器的逻辑。
- 如果您是新用户,程序将提示您等待设置主密码,以访问您的密码库。设置后,主密码将使用 hashlib Python 模块加密,如下面的代码 sn-p 所示。 key 和 salt 用于加密密码,两者都以二进制值的形式存储在数据库中。这些值使用 psycopg2 Python 模块发送到数据库。
- 如果您是现有用户,程序将提示您等待已设置的主密码,以便您可以使用密码库进行访问。程序将从数据库中获取 key 和 salt,使用 salt 创建一个 new key 并查看 key 和 新键 值匹配。如果是,则授予访问权限,否则拒绝访问保管库。
但是,我遇到了以下问题:存储在数据库中的二进制数据(key和salt)与Python中的二进制数据(key和salt)不一样。您将在下面找到我的代码:
import psycopg2
from psycopg2.extensions import ISOLATION_LEVEL_AUTOCOMMIT
import sys
import os
import hashlib
# This connects to PSQL
connection = psycopg2.connect(user="postgres",
password="abc",
host="localhost",
port="5432",
dbname="passwordmanager")
connection.set_isolation_level(ISOLATION_LEVEL_AUTOCOMMIT)
cur = connection.cursor()
salt = b""
key = b""
new_key = b""
stored_salt = b""
def welcome_n(): # This welcomes a new user without a master password set
user_input = input("Welcome! You need to set a master password"
" before you can start storing passwords - continue?\n y/n: ")
valid = False
while not valid:
if user_input == "y":
password_input = input("Please choose your password:\n")
global salt
global key
salt = os.urandom(32)
key = hashlib.pbkdf2_hmac(
"sha256",
password_input.encode("utf-8"),
salt,
100000
)
# PSQL commands to store salt and key
psycopg2.Binary(key)
psycopg2.Binary(salt)
cur.execute("INSERT INTO master (key, salt) VALUES (%s, %s)",
(key, salt))
valid = True
print(key) # b'\xfe\xfdO{\xd6?\xa1\x8d(\xbb\xb3r\x8a\xbc\xd6&t\x11[\x06\x110`\xb3\xfa\x91\xee\xc7x\x14\xddR'
key = b""
elif user_input == "n":
print("Quiting program.")
sys.exit()
else:
user_input = input("Invalid input. Please choose either 'y' or 'n'.\n y/n: ")
def welcome_o(): # This welcomes an existing user with a master password set already
password_to_check = input("Welcome! Enter your password to access the password safe:\n")
# Encrypting the password given
global salt
global key
global new_key
global stored_salt
cur.execute("SELECT key FROM master;")
key = cur.fetchone() # The key variable now has the fetched binary key from database
cur.execute("SELECT salt FROM master;")
stored_salt = cur.fetchone() # The stored_salt variable now has the fetched binary salt from database
new_key = hashlib.pbkdf2_hmac("sha256", password_to_check.encode("utf-8"), b"stored_salt", 10000)
# A new key has been generated using the fetched salt
if new_key == key:
print("Password is correct")
else:
print("Incorrect Password")
# Checking password similarities
print(key) # (<memory at 0x03B96388>,)
print(new_key) # b"k\r\xd8\xcfU\x05x\xfc'9\xaaC\x1fp~*9av6k^\xeeec\xef\xc5\xe3\xf1^\x883"
welcome_n()
welcome_o()
如前所述,存储在数据库中的二进制数据与 Python 中的二进制数据不同。我们可以在 key 中看到;
Python 二进制 = b'\xfe\xfdO{\xd6?\xa1\x8d(\xbb\xb3r\x8a\xbc\xd6&t\x11[\x06\x110`\xb3\xfa\x91\xee \xc7x\x14\xddR'
对
PSQL 二进制 = \xfefd4f7bd63fa18d28bbb3728abcd62674115b06113060b3fa91eec77814dd52
我遇到的另一个问题是,当我尝试在屏幕上打印密钥时,我得到了 (,) 如上所示,而新键显示为 b"k\r\xd8\xcfU\x05x\xfc'9\xaaC\x1fp~*9av6k^\xeeec\xef\xc5\xe3\xf1^\x883" .到目前为止,我的猜测是我没有正确地将数据输入到数据库中并且没有正确提取它,这意味着二进制数据被变形了。我还想提一下,保存主密码二进制数据的表的 key column 和 salt column 数据类型设置为 BYTEA。 您可以在下面找到表架构:
Column | Type | Collation | Nullable | Default | Storage | Stats target | Description
-------+--------+-----------+----------+------------------------------------+---------+--------------+-------------
id | bigint | | not null | nextval('master_id_seq'::regclass) | plain | |
key | bytea | | not null | | extended| |
salt | bytea | | not null | | extended| |
非常感谢任何形式的反馈,我是编程新手,我正在寻求改进和学习新事物!
【问题讨论】:
-
你能告诉我们相关表的架构吗?
-
您正在运行
pbkdf2_hmac不同的迭代。它们应该共享一个常量。 -
@Schwern Here's the schema.
-
好的,很好,你正在使用
bytea。如果您可以edit 回答您的问题。避免截图,粘贴文本。 -
我已经更新了答案。通过这些修复,代码现在可以工作了。在掌握 Python 和 SQL 的基础知识后,考虑处理二进制数据。
标签: python database postgresql binary-data