Python3使用gnupg.py解密文件时字符串密码与字节输入要求冲突问询
问题根源
你遇到的两个异常本质都和Python3的字符串/字节拆分有关,不存在“需要字符串格式密码的加密文件”这一情况:
- 读阻塞:不是
_io.BufferedReader的问题,是密码写入时没有正确完成,gpg进程一直等待标准输入的密码,没有输出解密内容导致读操作挂起。你加的O_NONBLOCK属于绕开表象的错误修复,还会引入读空的异常。 - 密码错误:你在终端输入的字符串密码会被终端默认编码转为字节传给gpg,Python3中你转字节时用的编码和终端编码不一致,导致传给gpg的字节序列和正确密码的字节序列不匹配,才会提示密码错误。
修复步骤
1. 修复内部_write_passphrase方法
修改该方法,按GPG对象指定的编码将字符串密码转为字节,写入后强制刷新缓冲区:
def _write_passphrase(self, stdin, passphrase, encoding): # 字符串转字节,用GPG实例声明的编码,和Python2行为对齐 if isinstance(passphrase, str): passphrase = passphrase.encode(encoding) # 写入密码+换行,和终端输入时按下回车的行为一致 stdin.write(passphrase + b'\n') # 强制清空缓冲区,确保密码立即发送给gpg进程 stdin.flush()
2. 去掉冗余的非阻塞IO设置
删掉你业务代码里fcntl修改O_NONBLOCK的三行代码,密码写入正确的情况下,读stdout不会阻塞。
3. 可选:直接使用官方gnupg接口
你用的0.4.6版本gnupg已经原生支持Python3,不需要自己封装流处理逻辑,直接调用官方接口即可:
import gnupg gpg = gnupg.GPG() input_path = "/tmp/encryp_input_file.dat.gpg" pgp_password = 'XXXXXXXXXX' with open(input_path, 'rb') as f: # 直接传入文件流,官方已经处理了所有IO逻辑 decrypted = gpg.decrypt_file(f, passphrase=pgp_password) # 解密后的内容存在decrypted.data中,是字节类型,需要的话自行decode为字符串 print("解密结果:", decrypted.data)
验证说明
如果你的密码包含非ASCII字符,且之前Python2环境用的不是utf-8编码,初始化GPG对象时指定对应编码即可:
gpg = gnupg.GPG(encoding='gbk') # 替换为你实际用的编码
内容的提问来源于stack exchange,提问作者Uncle Taco
相关产品推荐
相关产品推荐

