Ubuntu 20.04下python-gnupg无法找到私钥的问题求助
我有一台Ubuntu 20.04服务器,运行Python脚本解密PGP加密文件。已将PGP密钥添加至密钥环,命令行解密操作正常:
gpg --output test.zip --decrypt myfile.pgp
Python脚本使用python-gnupg库,代码片段如下:
import gnupg gpg = gnupg.GPG(gpgbinary='/usr/bin/gpg') stream = open('myfile.pgp', "rb") data = gpg.decrypt_file(stream, output=f'output.zip') print(data.status)
遇到的问题:直接运行脚本时,data.status返回no secret key,无法找到私钥;但刚通过命令行完成解密操作后立即运行脚本,解密就能成功(data.status返回decryption ok)。开启verbose=True后,错误信息显示:
gpg: public key decryption failed: Inappropriate ioctl for device
已尝试在脚本中指定密钥目录,但无效果,求解决办法。
1. 为GPG显式指定TTY
Inappropriate ioctl for device错误的核心原因是:命令行执行gpg时能获取到终端交互环境,但Python脚本运行时可能没有绑定TTY,导致GPG无法完成密码验证等交互步骤。可以在脚本中手动设置TTY环境变量:
import os import gnupg # 绑定当前终端TTY到GPG环境变量 os.environ['GPG_TTY'] = os.ttyname(0) gpg = gnupg.GPG(gpgbinary='/usr/bin/gpg') stream = open('myfile.pgp', "rb") data = gpg.decrypt_file(stream, output=f'output.zip') print(data.status)
如果脚本在无终端环境(如cron任务)运行,需额外配置pinentry为非交互式模式,或预先缓存密钥密码。
2. 明确指定密钥环目录
确保Python脚本使用与命令行相同的密钥环,可显式指定GNUPG的工作目录:
gpg = gnupg.GPG( gpgbinary='/usr/bin/gpg', homedir='/home/your-username/.gnupg' # 替换为你的GNUPG实际目录 )
注意要保证脚本运行用户对该目录拥有读写权限。
3. 配置密钥密码缓存
命令行执行后脚本能成功解密,是因为gpg-agent缓存了密钥密码。可以通过修改gpg-agent配置延长缓存时间,或在脚本中传入密码(不建议明文硬编码,优先用环境变量):
- 修改
~/.gnupg/gpg-agent.conf,添加缓存配置:
default-cache-ttl 3600 # 默认缓存1小时 max-cache-ttl 7200 # 最长缓存2小时
修改后重启gpg-agent:
gpg-connect-agent reloadagent /bye
- 脚本中通过环境变量传入密码:
import os import gnupg gpg = gnupg.GPG(gpgbinary='/usr/bin/gpg') stream = open('myfile.pgp', "rb") data = gpg.decrypt_file( stream, output=f'output.zip', passphrase=os.environ.get('PGP_PASSPHRASE') ) print(data.status)
运行脚本前需先设置环境变量:export PGP_PASSPHRASE="your-passphrase"
4. 检查脚本运行用户
确认Python脚本的运行用户与命令行执行gpg的用户一致。如果脚本以root或其他用户身份运行,会访问不同的密钥环,导致找不到私钥。可在脚本和命令行分别执行whoami验证用户是否相同。
内容的提问来源于stack exchange,提问作者Andy

