带有 CLI 密码提示的 rpmsign

带有 CLI 密码提示的 rpmsign

我在 Fedora 25 (F25) 工作站(KDE spin)上工作。我正在编写一些脚本来执行自动化测试。

其中一项自动化测试涉及调用 RPMSIGN(8) 程序,该程序又调用 GPG(1) 将数字签名附加到我正在创建的某些 RPM 文件中。当然,GPG 使用 pinentry(PIN 输入)来提示用户输入 RPM 签名密钥(RSA 密钥对)的密码。我想让人类脱离循环,完全自动化为 RPM 签名密钥提供密码的任务。(是的,我知道安全隐患。这只是一个自动化测试环境,而不是生产主机,所以我不太担心安全性。在生产版本中,用户将手动输入 RPM 签名密钥的密码。)

过去,我使用 EXPECT(1) 脚本等待 GPG 将文本“输入密码短语:”输出到控制台,然后 EXPECT 脚本将输入密码短语,然后继续。效果很好。

在 F25 中,pinentry 功能打破了我现有的基于 EXPECT 的解决方案,用于自动输入 RPM 签名密钥的密码。

当我在此 F25 主机上的 GUI 控制台窗口中运行 RPMSIGN 时,GPG 使用 pinentry 弹出一个 GUI 对话框,要求用户(我)输入 RPM 签名密钥的密码。当然,这种密码输入行为会干扰并阻止密码短语的自动输入。

如果我创建一个暂时取消设置 DISPLAY 环境变量的 Bash 脚本,那么我将不再获得 GUI 对话框,

#!/bin/bash
DISPLAY_SAVE=$DISPLAY
unset DISPLAY
rpmsign --resign "/path/to/test-1.0.0-1.fc25.noarch.rpm"
export DISPLAY=$DISPLAY_SAVE

但现在我在控制台上看到了该对话框的 ncurses 版本:

+----------------------------------------------------------------+
| Please enter the passphrase to unlock the OpenPGP secret key:  |
| "Testing (rpm-sign)"                                           |
| 1024-bit RSA key, ID 0123456789ABCDEF,                         |
| created 2016-12-02.                                            |
|                                                                |
|                                                                |
| Passphrase: __________________________________________________ |
|                                                                |
|         <OK>                                    <Cancel>       |
+----------------------------------------------------------------+

同样,pinentry-curses 的控制台“对话框”会干扰并阻止自动输入密码。

我不想永久修改或禁用 pinentry 模块;我只是想暂时禁用它们以返回 GPG 的 CLI 提示“输入密码:”(或现在的提示字符串),而不会受到 pinentry 的干扰。

对于通过 CLI 完全自动化输入 RPM 签名密钥的密码短语而不存在 pinentry 干扰,有什么建议吗?

答案1

感谢@Joe Damato 向我指出了该gpg-preset-passphrase实用程序。下面描述的解决方案是在已安装的 Fedora 25 主机上开发和测试的gnupg2-2.1.x

(注意,我还没有弄清楚如何在运行旧版本 GnuPG 的平台上确定 RPM 签名密钥的 keygrip 值,因为它们不支持该--with-keygrip选项。如果有人想对此解决方案发表评论,请这样做。)

确保~/.gnupg/gpg-agent.conf包含该行。

allow-preset-passphrase

修改后~/.gnupg/gpg-agent.conf重新加载gpg-agent。

$ gpg-connect-agent reloadagent /bye
OK

列出您的 GPG 密钥以获得 RPM 签名密钥的八个十六进制数字密钥 ID。在此示例中,密钥 ID 为0123ABCD

$ gpg --list-keys
/home/me/.gnupg/pubring.gpg
-----------------------------------
pub   1024R/0123ABCD 2015-06-13
uid                  Test (rpm-sign)

获取 RPM 签名密钥的 keygrip 代码。 (注意,在我用于测试的 RHEL 7.2 和 Fedora 20 主机上,GPG2(1)这些主机上的程序无法识别该--with-keygrip选项。)

$ gpg2 --with-keygrip -K 0123ABCD
sec   rsa1024 2015-06-13 [SCEA]
      0A1B2C3D4E5F6A7B8C9D0E0F1A2B3C4D0123ABCD
      Keygrip = 2EACA0C5A4B46168EB91970B6715AF1AA52968BE
uid           [ unknown] Test (rpm-sign)

缓存 RPM 签名密钥的密码。在下面显示的命令行中,替换'PASSPHRASE'为 RPM 签名密钥的实际密码。

$ /usr/libexec/gpg-preset-passphrase --passphrase 'PASSPHRASE' --preset 2EACA0C5A4B46168EB91970B6715AF1AA52968BE

:: 测试 ::

创建未签名的测试 RPM 文件。验证测试 RPM 文件是否未签名。

$ rpm --checksig test-1.0.0-1.f25.noarch.rpm
test-1.0.0-1.fc25.noarch.rpm: sha1 md5 OK

验证在签署测试 RPM 文件时RPMSIGN(8)是否使用缓存的密码(即,不会RPMSIGN(8)提示您输入 RPM 签名密钥的密码)。

$ rpmsign --resign test-1.0.0-1.f25.noarch.rpm

验证测试 RPM 文件是否已签名。

$ rpm --checksig test-1.0.0-1.f25.noarch.rpm
test-1.0.0-1.fc25.noarch.rpm: rsa sha1 (md5) pgp md5 OK

:: 附录 1 (2016-12-17) ::

根据这个GnuPG 第 2331 期网页

gpg1 不知道 keygrips。 gpg1 使用指纹作为 gpg-agent 的缓存 ID,而不是 keygrip。 gpg1 使用的代理命令 GET_PASSPHRAE 使用与 gpg-preset-passphrases 使用的不同的缓存模式。因此,即使您用(子)钥匙的指纹替换钥匙柄,它也不起作用。

无论如何,我已经在 RHEL7 主机上使用 GnuPG 版本 2.0.x 进行了一些测试,但gpg-preset-passphrase似乎不受支持。我只能gpg-preset-passphrase使用 GnuPG 版本 2.1.x。

参考

GnuPG ArchWiki

答案2

%__gpg_sign_cmd通过在文件中添加/修改宏.rpmmacros,您可以告诉 gpg 从文件中读取密码。使用rpm --showrc查看当前的情况%__gpg_sign_cmd,然后将其放入.rpmmacros文件中,并添加以下内容:

--batch --pinentry-mode loopback --passphrase-file /path/to/passphrase-file

\如果您有多行值,请确保除最后一行之外的每一行都以 结束。

这将导致 gpg 不会以任何方式提示输入密码,而是从定义的文件中读取它。这构成了一个安全风险当然,所以请考虑这是否是您想要做的事情,并采取任何必要的措施来确保它的安全(例如所有权和许可)。

完整的%__gpg_sign_cmd示例.rpmmacros

%__gpg_sign_cmd %{__gpg} \
    gpg --no-verbose --no-armor --batch --pinentry-mode loopback \
    --passphrase-file /path/to/passphrase-file \
    %{?_gpg_digest_algo:--digest-algo %{_gpg_digest_algo}} \
    --no-secmem-warning \
    -u "%{_gpg_name}" -sbo %{__signature_filename} %{__plaintext_filename}

签署包裹:

$ rpm --checksig somepackage.rpm 
somepackage.rpm: sha1 md5 OK

$ rpmsign --addsign somepackage.rpm
somepackage.rpm:

$ rpm --checksig somepackage.rpm 
somepackage.rpm: rsa sha1 (md5) pgp md5 OK

答案3

解决此类问题的一种方法是使用gpg-agent,它管理 GPG 密钥。您可以结合使用该工具gpg-preset-passphrase将密码短语植入gpg-agent缓存中。阅读有关 gpg-agent 的更多信息这里。这将使您无需手动输入密码,以便执行自动化任务。

顺便说一句,我写了一篇有用的博客文章GPG 签名和验证 RPM 包和 YUM 存储库您可能也会觉得有用。

答案4

对于带有 GPG 2.0 的 CentOS7(我猜是 RedHat7), 和pinentry-mode不起作用gpg-preset-passphrase

我设法让它工作使用预计

#!/usr/bin/expect -f

### rpm-sign.exp -- Sign RPMs by sending the passphrase.
 
spawn rpm --addsign {*}$argv
expect -exact "Enter pass phrase: "
send -- "Secret passphrase\r"
expect eof

## end of rpm-sign.exp

用法

$ ./rpm-sign.exp PACKAGE-FILE

致谢亚伦·S·霍利 (Aaron S. Hawley)GPG 在无人值守的情况下签署 RPM

相关内容