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 . . .
问题根源与修复方案
核心错误点
- 直接传递文件对象给Fernet:把
open()返回的文件句柄(BufferedReader)传给了Fn(key),但Fernet需要的是文件里的密钥内容(bytes或ASCII字符串),不是文件对象本身。 - 文件操作逻辑错误:
- 加密时打开数据库用
w模式(文本写入),但需先读原数据要用rb模式,写加密数据要用wb模式(Fernet加密结果是bytes)。 - 尝试对文件对象调用
encode(),这是错误的,应该先读取文件内容再处理。
- 加密时打开数据库用
- 类方法调用问题:
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
相关产品推荐
相关产品推荐

