Fernet同密钥解密后文件为空 原因及加密内容恢复方法
问题描述
我在加密逻辑中生成密钥,使用Fernet(key).encrypt(contents)对文件内容进行加密。后续使用同一密钥调用Fernet(key).decrypt(contents)解密内容时,所有文件内容被清空,加密后的文件变为空文件。
加密代码如下:
root_dir = "test_dir" all_files = [] for file in os.listdir(root_dir): if os.path.isfile(os.path.join(root_dir, file)): all_files.append(os.path.join(root_dir, file)) key = Fernet.generate_key() with open("key.key", "wb") as keyfile: keyfile.write(key) for file in all_files: with open(file, "wb+") as raw_file: contents = raw_file.read() enc_contents = Fernet(key).encrypt(contents) raw_file.write(enc_contents)
解密代码如下:
with open("key.key", "rb") as thekey: code = thekey.read() for file in all_files: with open(file, "rb") as enc_file: contents = enc_file.read() raw_contents = Fernet(code).decrypt(contents) print("Raw contents: ", raw_contents) with open(file, "wb") as enc_file: enc_file.write(raw_contents)
问题原因
问题根源在加密代码的文件打开模式:
- 加密环节使用
wb+模式打开目标文件,该模式触发时会立即清空文件全部原有内容,后续执行read()读取到的本身就是空值,你加密的对象从一开始就是空字节,最终写回文件的加密内容对应的就是空数据。 - 解密代码的逻辑本身没有错误,只是因为待解密的文件存的本来就是空内容的加密结果,解密后自然得到空值,写回后文件就保持为空,和密钥是否匹配没有关系。
数据恢复结论
原有文件内容无法通过代码手段恢复。
使用wb+打开文件的瞬间,文件系统就已经将原文件占用的存储块标记为可覆写状态,后续写入的空内容加密结果已经覆盖了原有数据的存储位置,没有办法通过常规手段找回。如果磁盘没有发生大量后续写入,可尝试使用专业磁盘数据恢复工具扫描残留碎片,但成功率无法保证,不属于代码可解决的范畴。
正确写法修正
后续做文件加解密操作时,必须将读、写操作拆分,禁止使用会提前截断文件的模式打开待读取的原文件:
- 加密时先以只读
rb模式打开文件,将全部内容读取到内存完成加密计算后,再以wb模式打开文件写入加密结果,避免同一文件句柄读写导致的内容提前丢失。更稳妥的方式是先将加密结果写入临时文件,校验无误后再替换原文件。
修正后的加密代码片段:
for file in all_files: # 第一步:只读模式读取原文件内容,不会修改文件 with open(file, "rb") as raw_file: contents = raw_file.read() # 内存中完成加密计算 enc_contents = Fernet(key).encrypt(contents) # 第二步:写入模式打开文件,此时再覆盖原内容 with open(file, "wb") as raw_file: raw_file.write(enc_contents)
- 对重要文件执行加解密操作前,必须先做全量备份,避免代码逻辑错误导致不可逆的数据丢失。
内容的提问来源于stack exchange,提问作者Chinmay Chhajed
相关产品推荐
相关产品推荐

