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

Python3使用gnupg.py解密文件时字符串密码与字节输入要求冲突问询

问题根源

你遇到的两个异常本质都和Python3的字符串/字节拆分有关,不存在“需要字符串格式密码的加密文件”这一情况:

  1. 读阻塞:不是_io.BufferedReader的问题,是密码写入时没有正确完成,gpg进程一直等待标准输入的密码,没有输出解密内容导致读操作挂起。你加的O_NONBLOCK属于绕开表象的错误修复,还会引入读空的异常。
  2. 密码错误:你在终端输入的字符串密码会被终端默认编码转为字节传给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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.25 11:45:02