You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Python cryptography.fernet模块TypeError报错,求解决方法

密码存储系统Fernet模块报错:TypeError: argument should be a bytes-like object or ASCII string, not 'BufferedReader'

我正在开发一款密码存储系统,使用Python的cryptography.fernet模块时触发了上述错误,谷歌搜索后没找到有效解决方案,特此求助。

相关代码

import PGL
from cryptography.fernet import Fernet as Fn
class APM():
    class database():
        def genkey():
            keyfile = open("D:\\CODING\\Python\\APMKEY.APMKEY", "wb")
            key = Fn.generate_key()
            keyfile.write(key)
        def encrypt(self):
            key = open("D:\\CODING\\Python\\APMKEY.APMKEY", "rb")
            database = open("D:\\CODING\\Python\\APMDatabase.APMDATA", "w")

            newdata = Fn(key).encrypt(database.encode())
            database.write(newdata)
        def decrypt(self):
            key = open("D:\\CODING\\Python\\APMKEY.APMKEY", "rb")
            database = open("D:\\CODING\\Python\\APMDatabase.APMDATA", "w")

            newdata = Fn(key).decrypt(database)
            database.write(newdata)
        def access(self):
            database = open("D:\\CODING\\Python\\APMDatabase.APMDATA", "r")
            content = database.readlines()
            print(content)
        def write(self):
            database = open("D:\\CODING\\Python\\APMDatabase.APMDATA", "a")
            database.write("\"NAME OF SITE\", \"WEBSITE URL\", \"USERNAME\", \"PASSWORD\", \"XTRA INFO\"\n")
        def reencrypt():
            key = Fn.generate_key()
            keyfile = open("D:\\CODING\\Python\\APMKEY.APMKEY", "r")
            oldkey = keyfile.read()
            keyfile.close()
            keyfile = open("D:\\CODING\\Python\\APMKEY.APMKEY", "w")
            keyfile.write(key)
            APM.database.decrypt(oldkey)
            APM.database.encrypt(key)

    class gen():
        def password():
            PGL.gen.password()
        def username():
            PGL.gen.username()

APM.database.encrypt("a")

补充说明

PGL是用于生成密码和用户名的自定义模块,调用APM.database.encrypt("a")中的"a"是self的占位符,相关实现尚未完成。

报错回溯信息

Traceback (most recent call last):
  File "D:\CODING\Python\APM.py", line 51, in <module>
    APM.database.encrypt("a")
  File "D:\CODING\Python\APM.py", line 18, in encrypt
    newdata = Fn(key).encrypt(database.encode())
  File "C:\Users\Anton\AppData\Local\Programs\Python\Python310\lib\site-packages\cryptography\fernet.py", line 33, in __init__
    key = base64.urlsafe_b64decode(key)
  File "C:\Users\Anton\AppData\Local\Programs\Python\Python310\lib\base64.py", line 131, in urlsafe_b64decode
    s = _bytes_from_decode_data(s)
  File "C:\Users\Anton\AppData\Local\Programs\Python\Python310\lib\base64.py", line 45, in _bytes_from_decode_data
    raise TypeError("argument should be a bytes-like object or ASCII "
TypeError: argument should be a bytes-like object or ASCII string, not 'BufferedReader'
Press any key to continue . . .

问题根源与修复方案

核心错误点

  1. 直接传递文件对象给Fernet:把open()返回的文件句柄(BufferedReader)传给了Fn(key),但Fernet需要的是文件里的密钥内容(bytes或ASCII字符串),不是文件对象本身。
  2. 文件操作逻辑错误:
    • 加密时打开数据库用w模式(文本写入),但需先读原数据要用rb模式,写加密数据要用wb模式(Fernet加密结果是bytes)。
    • 尝试对文件对象调用encode(),这是错误的,应该先读取文件内容再处理。
  3. 类方法调用问题:encrypt是实例方法,直接用类调用并传"a"当占位符不符合规范,应改成类方法或创建实例调用。

修正后的代码示例

import PGL
from cryptography.fernet import Fernet as Fn

class APM():
    class database():
        @classmethod
        def genkey(cls):
            # 用with自动管理文件关闭
            with open("D:\\CODING\\Python\\APMKEY.APMKEY", "wb") as keyfile:
                key = Fn.generate_key()
                keyfile.write(key)

        @classmethod
        def encrypt(cls):
            # 读取密钥内容(bytes)
            with open("D:\\CODING\\Python\\APMKEY.APMKEY", "rb") as keyfile:
                key = keyfile.read()
            # 读取原数据库内容
            with open("D:\\CODING\\Python\\APMDatabase.APMDATA", "rb") as dbfile:
                data = dbfile.read()
            # 加密并写入
            fernet = Fn(key)
            encrypted_data = fernet.encrypt(data)
            with open("D:\\CODING\\Python\\APMDatabase.APMDATA", "wb") as dbfile:
                dbfile.write(encrypted_data)

        @classmethod
        def decrypt(cls):
            with open("D:\\CODING\\Python\\APMKEY.APMKEY", "rb") as keyfile:
                key = keyfile.read()
            with open("D:\\CODING\\Python\\APMDatabase.APMDATA", "rb") as dbfile:
                encrypted_data = dbfile.read()
            fernet = Fn(key)
            decrypted_data = fernet.decrypt(encrypted_data)
            # 写入解密后的数据
            with open("D:\\CODING\\Python\\APMDatabase.APMDATA", "wb") as dbfile:
                dbfile.write(decrypted_data)

        @classmethod
        def access(cls):
            # 先解密再读取,避免读加密乱码
            cls.decrypt()
            with open("D:\\CODING\\Python\\APMDatabase.APMDATA", "r") as dbfile:
                content = dbfile.readlines()
                print(content)
            # 读完重新加密
            cls.encrypt()

        @classmethod
        def write(cls):
            # 先解密,写入后再加密
            cls.decrypt()
            with open("D:\\CODING\\Python\\APMDatabase.APMDATA", "a") as dbfile:
                dbfile.write("\"NAME OF SITE\", \"WEBSITE URL\", \"USERNAME\", \"PASSWORD\", \"XTRA INFO\"\n")
            cls.encrypt()

        @classmethod
        def reencrypt(cls):
            # 生成新密钥
            new_key = Fn.generate_key()
            # 读取旧密钥
            with open("D:\\CODING\\Python\\APMKEY.APMKEY", "rb") as keyfile:
                old_key = keyfile.read()
            # 写入新密钥
            with open("D:\\CODING\\Python\\APMKEY.APMKEY", "wb") as keyfile:
                keyfile.write(new_key)
            # 用旧密钥解密,新密钥加密
            with open("D:\\CODING\\Python\\APMDatabase.APMDATA", "rb") as dbfile:
                encrypted_data = dbfile.read()
            fernet_old = Fn(old_key)
            decrypted_data = fernet_old.decrypt(encrypted_data)
            fernet_new = Fn(new_key)
            new_encrypted_data = fernet_new.encrypt(decrypted_data)
            with open("D:\\CODING\\Python\\APMDatabase.APMDATA", "wb") as dbfile:
                dbfile.write(new_encrypted_data)

    class gen():
        @classmethod
        def password(cls):
            PGL.gen.password()
        @classmethod
        def username(cls):
            PGL.gen.username()

# 第一次运行先生成密钥
# APM.database.genkey()
# 调用加密方法
APM.database.encrypt()

关键修改说明

  • 所有数据库操作方法改为@classmethod,可直接通过类调用,无需占位符"a"。
  • 用with语句处理文件,自动关闭句柄,避免资源泄漏。
  • 读取密钥和数据库内容时调用read()获取实际内容,而非传递文件对象。
  • 加密/解密基于bytes数据处理,文件模式用rb/wb确保字节流操作正确。
  • 调整access和write逻辑:先解密操作,完成后重新加密,保证数据库始终处于加密状态。

内容的提问来源于stack exchange,提问作者Anton Chernyshov

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.15 05:45:32