![当收到太多请求时,gpg-agent“忘记”密钥密码](https://linux22.com/image/229989/%E5%BD%93%E6%94%B6%E5%88%B0%E5%A4%AA%E5%A4%9A%E8%AF%B7%E6%B1%82%E6%97%B6%EF%BC%8Cgpg-agent%E2%80%9C%E5%BF%98%E8%AE%B0%E2%80%9D%E5%AF%86%E9%92%A5%E5%AF%86%E7%A0%81.png)
我正在运行 Ubuntu(通过 Regolith),登录时我的 gpg 密钥已解锁。我正在并行运行多个解密操作,我注意到,如果我得到 7 以上,gpg-agent
将“忘记”密钥已解锁然后我被提示输入 pinentry。
❯ gpg --version
gpg (GnuPG) 2.2.27
libgcrypt 1.10.1
我做了一个最小的工作示例来在 python 中演示这一点。
创建一个测试文件来解密:echo "something" | gpg --encrypt -o test.gpg
.在 shell 中运行gpg --decrypt test.gpg
不会提示输入密码。
使用下面的脚本,如果将其WORKERNUM
设置为低于 8(在我的机器上,但将其设置为 1,我想应该适用于任何机器),则脚本很乐意解密,而无需询问密码。但是,如果我将其提高到 8 或以上,我就会开始收到输入密码的请求,尽管似乎并非来自每个进程,而只是其中的一些进程。进程的执行显然也开始挂起(我假设它们正在等待gpg-agent
)。
import subprocess
import multiprocessing as mp
import time
the_queue = mp.Queue()
WORKERNUM = 7
def worker_main(queue):
while True:
msg = queue.get(True)
print(time.time(), msg)
out = subprocess.run(["gpg", "--decrypt", "test.gpg"], capture_output=True)
print(msg, time.time(), out.stdout)
the_pool = mp.Pool(WORKERNUM, worker_main, (the_queue,))
counter = 0
while True:
counter += 1
the_queue.put(counter)
print(the_queue.qsize())
while the_queue.qsize() > 10:
time.sleep(0.1)
我尝试传递--batch
给解密命令,但这并没有改变任何东西。我一直在浏览手册页gpg
,看看gpg-agent
是否提到了与此相关的内容,但我找不到任何内容。我有两个问题:
a)为什么会发生这种情况,b)我是否可以配置一些东西,这样就不必计算出处理池的最大大小来避免这种情况,而是gpg
处理这个问题并且我没有得到 pinentry
答案1
经过仔细监测journalctl
我发现实际的错误是Cannot allocate memory
。基于这次讨论,gpg-agent
如果多个线程尝试访问安全内存,则可能会耗尽安全内存。设置auto-expand-secmem 100
即可~/.gnupg/gpg-agent.conf
解决问题。
--auto-expand-secmem n Allow Libgcrypt to expand its secure memory area as required. The optional
value n is a non-negative integer with a suggested size in bytes of each
additionally allocated secure memory area. The value is rounded up to the next
32 KiB; usual C style prefixes are allowed. For an heavy loaded gpg-agent with
many concurrent connection this option avoids sign or decrypt errors due to out
of secure memory error returns.