Thanks to @Joe Damato for pointing me toward the gpg-preset-passphrase
utility. The solution described below was developed and tested on a Fedora 25 host with gnupg2-2.1.x
installed.
(n.b. I haven't yet figured out how to determine the RPM signing key's keygrip value on platforms running older versions of GnuPG because they don't support the --with-keygrip
option. If someone would like to comment on a solution for this, please do.)
Ensure ~/.gnupg/gpg-agent.conf
contains the line.
allow-preset-passphrase
After modifying ~/.gnupg/gpg-agent.conf
reload the gpg-agent.
$ gpg-connect-agent reloadagent /bye
OK
List your GPG keys to obtain the eight hexidecimal digit key ID for your RPM signing key. In this excample, the key ID is 0123ABCD
.
$ gpg --list-keys
/home/me/.gnupg/pubring.gpg
-----------------------------------
pub 1024R/0123ABCD 2015-06-13
uid Test (rpm-sign)
Get the keygrip code for the RPM signing key. (n.b. On the RHEL 7.2 and Fedora 20 hosts I use for testing, the GPG2(1)
program on those hosts didn't recognize the --with-keygrip
option.)
$ gpg2 --with-keygrip -K 0123ABCD
sec rsa1024 2015-06-13 [SCEA]
0A1B2C3D4E5F6A7B8C9D0E0F1A2B3C4D0123ABCD
Keygrip = 2EACA0C5A4B46168EB91970B6715AF1AA52968BE
uid [ unknown] Test (rpm-sign)
Cache the passphrase for the RPM signing key. In the command line shown below, replace 'PASSPHRASE'
with the actual passphrase for the RPM signing key.
$ /usr/libexec/gpg-preset-passphrase --passphrase 'PASSPHRASE' --preset 2EACA0C5A4B46168EB91970B6715AF1AA52968BE
:: TEST ::
Create a test RPM file that is not signed. Verify that the test RPM file is not signed.
$ rpm --checksig test-1.0.0-1.f25.noarch.rpm
test-1.0.0-1.fc25.noarch.rpm: sha1 md5 OK
Verify that RPMSIGN(8)
uses the cached password--i.e., that RPMSIGN(8)
does not prompt you to enter the passphrase for the RPM signing key--when signing the test RPM file.
$ rpmsign --resign test-1.0.0-1.f25.noarch.rpm
Verify that the test RPM file is signed.
$ rpm --checksig test-1.0.0-1.f25.noarch.rpm
test-1.0.0-1.fc25.noarch.rpm: rsa sha1 (md5) pgp md5 OK
:: ADDENDUM 1 (2016-12-17) ::
According to this GnuPG Issue 2331 webpage:
gpg1 does not known about keygrips. Instead of the keygrip, gpg1 uses the fingerprint as cacheid for gpg-agent. The agent's command GET_PASSPHRAE, as used by gpg1, uses a different cache mode from what gpg-preset-passphrases uses. Thus even if you replace the keygrip with the fingerprint of the (sub)key, it won't work.
For what it's worth, I've done some testing with GnuPG version 2.0.x on RHEL7 hosts and gpg-preset-passphrase
doesn't seem to be supported. I can only get gpg-preset-passphrase
to work with GnuPG version 2.1.x.
References
GnuPG ArchWiki
Best Answer
The main point to understand about GPG checking for packages is that the GPG signature is embedded within the package, and the GPG keys are stored in the rpmdb. There is no secure API to ask "What key is package X signed with" you can only ask "Is package X signed with a key in the rpmdb" and "Does key Y exist in the rpmdb". Also note that this means that a package can only be signed by one key, and that changing the signature changes the packages.
Yum performs a number of steps when it downloads a package from a repository configured with "gpgcheck = 1" (the default).
After the first package from a repository is downloaded, a simple "is this package signed with a known gpgkey" call is done. If it is, nothing is done. If it isn't a warning is displayed to the user. This is purely informational.
Before the transaction starts yum checks that the package is signed with a known gpgkey (one already installed in the rpmdb), if it is the package is valid and no other steps are performed. If not then it continues to #3.
Yum downloads all the files given in the "gpgkey" data for the repository that the package comes from. Yum parses that, ignoring any keys already present in the rpmdb. If there are no new keys, yum will fail.
If there is a "gpgcakey" specified for the repository, then yum will download all the files given in the "gpgcakey" data. Yum parses that, ignoring any keys already present in that repositories gpg keyring. If there are no gpgcakeys installed after parsing the file, yum will fail. If there are new gpgcakeys, then if they are already imported as CA keys for another repo. they are automatically imported. If this is the first tiem we've seen this CA key the user is asked if he wants to install the key (unless -y is given). If he says no to any key, yum fails (although all imported keys stay in the repo. gpg keyring).
If there is at least one valid "gpgcakey", yum will try to download a "gpgkey".asc file. If that doesn't exists, yum moves on to step #6 as though there was no gpgcakey. If it does exist then the "gpgkey" is tested against the "gpgcakey" and if it passes it's added to the rpmdb, if it fails then yum fails (although all imported keys stay in the rpmdb).
If there are new gpgkeys, then the user is asked if he wants to install each key (unless -y is given). If he says no to any key, yum fails.
After installing any new keys, yum again checks the package signature against the gpgkeys in the rpmdb. If this fails, yum fails.