pass程序是一个命令行实用程序,用于将密码和自由格式的额外数据存储在使用 gpg 加密的小文件中。它特别提供了一个 grep 子命令,用于通过额外数据查找密码。
但是这个 grep 子命令在我的计算机上运行速度非常慢。我存储了近 200 个密码,每个文件的内部解密方式gpg
如下(time
当然,前面没有):
% time gpg -d --quiet --yes --compress-algo=none --no-encrypt-to stackoverflow.gpg
the password output
user=0,000 sys=0,006 wall=0,382 (1,61)
挂钟时间大约为 0.4 秒,也就是说,grep 所有文件需要大约 1 分钟的时间。
正在gpg-agent
运行并且我有这个版本:
gpg(GnuPG)2.2.27
有两个原因导致速度很慢:
- 的启动
gpg
和通信gpg-agent
很慢,这是因为用户+系统时间相比之下较少。 gpg-agent
很慢,事实是,pass grep
运行一次后它的累计 CPU 时间增加了 60 秒,与完整运行的总时间非常吻合。
两者合在一起,都指向gpg-agent
,尽管我不知道为什么代理会这么慢。ps
我看到它运行如下
/bin/gpg-agent --sh --daemon
有人可以解释一下每个文件代理大约 0.3 CPU 秒是否合理,或者是否有办法改进这一点?
编辑:进一步的发现
附加strace
到代理后,我发现了这一点:
20200 14:57:03.701648 getrusage(RUSAGE_SELF, {ru_utime={tv_sec=133, tv_usec=890780}, ru_stime={tv_sec=0, tv_usec=99975}, ...}) = 0
20200 14:57:03.701666 clock_gettime(CLOCK_PROCESS_CPUTIME_ID, {tv_sec=133, tv_nsec=990762100}) = 0
20200 14:57:04.063523 getpid() = 18035
clock_gettime
通话之间间隔 360 毫秒getpid
。
使用 ltrace 的话:
20472 15:04:55.035574 strlen("my-password-here") = 10
20472 15:04:55.035641 gcry_kdf_derive(0x7d884b82c008, 10, 19, 2) = 0
20472 15:04:55.394727 gcry_cipher_setkey(0x7d884b82cbc0, 0x7d884b82c030, 16, 0x7d884b83c000) = 0
所以gcry_kdf_derive
需要 360 毫秒。无论它做什么,我是否可以通过一些配置设置让它将其结果缓存几秒钟。(... 去获取源代码)。
KDF 是密钥派生函数,可将密码转换为加密密钥。它需要密钥来解密您的密码。为了防止密码被猜到,它们在最初设计时都故意设计得很慢。
通常,一旦您输入了私钥的密码或最近使用了私钥,GPG 就会缓存它。但它认为它只对每个密钥执行此操作。如果这些密钥确实是使用来自 KDF 的相同密钥加密的(并且不会在每个 KDF 调用中包含来自密钥本身的唯一信息),那么您可能只能通过从 gcrypt 开始编写自己的代码来保留来自 KDF 的结果。另一种方法是使用 GPG 中的主密钥,该密钥使用单个 KDF 解锁,然后在缓存时用于解密各个密钥和密码。
我不知道这是否适用于您的系统。