Redhat – Bad signatures or NOKEY errors on RPMs I just signed

centos5digital-signaturesgpgredhatrpm

I'm having serious problems getting RPM signing working for RHEL / CentOS 5 hosts.

TL;DR: RPM signing isn't working, and it's working in a variety of insane and erratic ways depending on the exact GPG key size and format and even where it was generated, producing NOKEY errors when the key is shown by rpm -qa gpg-* as present; BAD signature errors on an RPM that was just signed on the same machine with the same key; invalid passphrase errors on a key where gpg accepts the passphrase directly without trouble; etc.


I have tested with 4096, 2048 and 1024 bit RSA keys, and a 2048 bit DSA key, doing the signing and the verification on the same CentOS 5.10 VM. Behaviour varies with key type and size, but I haven't found anything that actually works yet.

With names, emails and RPM filenames masked by XXX but no other edits, for example, the DSA 2048 key:

$ rpm --version
RPM version 4.4.2.3

$ gpg --list-secret 92fb1e62
sec   2048D/92FB1E62 2014-08-29 [expires: 2015-08-29]
uid                  XXX <XXX@XXX.com>
ssb   2048g/2E0F0A24 2014-08-29 [expires: 2015-08-29]

$ gpg -a --export 92fb1e62 > /tmp/packagers

$ sudo rpm --import /tmp/packagers

$ rpm -qa gpg*
gpg-pubkey-92fb1e62-54001945

$ rpmsign --define '%_gpg_name XXX@XXX.com' --resign test.el5.x86_64.rpm
Enter pass phrase: 
Pass phrase is good.
test.el5.x86_64.rpm:
gpg: WARNING: standard input reopened
gpg: WARNING: standard input reopened

$ rpm -v -K test.el5.x86_64.rpm
test.el5.x86_64.rpm:
    Header V3 DSA signature: NOKEY, key ID 92fb1e62
    Header SHA1 digest: OK (47271f9fa8ac0ce03b980ff75a37f10d3b78ee7c)
    MD5 digest: OK (f453985ee4331d36cb82d2c4f6009509)
    V3 DSA signature: NOKEY, key ID 92fb1e62

NOKEY? How does that make any sense?

I imported the key with rpm --import as normal. It imported with no errors. It's listed in the RPM DB. Yet RPM's verify command doesn't see it.

I see the same problem with a 4096 bit RSA key on CentOS 5.

(On Fedora 20, it instead fails with:

$ rpmsign --define '%_gpg_name XXX@XXX.com' --resign test.x86_64.rpm
Enter pass phrase: 
Pass phrase is good.
test.x86_64.rpm:
error: Unsupported PGP signature

… which is at least a failure at signing time, not later.)

If I use a 2048 or 1024 bit RSA key on CentOS 5, I instead get a BAD signature reported when the signature is verified, despite the fact that I just signed the RPM with that key:

$ gpg --import /mnt/repo/packaging-key-secret-1024
gpg: key 1FC138CC: secret key imported
gpg: key 1FC138CC: public key "XXX <XXX@XXX.com>" imported
gpg: Total number processed: 1
gpg:               imported: 1  (RSA: 1)
gpg:       secret keys read: 1
gpg:   secret keys imported: 1

$ gpg -a --export XXX@XXX.com > /tmp/packagers

$ sudo rpm --import /tmp/packagers

$ rpm --define '%_gpg_name XXX@XXX.com'  --resign test.x86_64.rpm
Enter pass phrase: 
Pass phrase is good.
test.x86_64.rpm:
gpg: WARNING: standard input reopened
gpg: WARNING: standard input reopened

$ $ rpm -v -K test.x86_64.rpm
test.x86_64.rpm:
Header V3 RSA/SHA1 signature: BAD, key ID 1fc138cc
Header SHA1 digest: OK (1befc128ddd02a79d1b1098bc16aff4532b5af6c)
V3 RSA/SHA1 signature: BAD, key ID 1fc138cc
MD5 digest: OK (2aaacbe1db08a2c63c94f2f705693c7d)

Seriously. W.T.F? I'm at a head-meets-wall level of frustration and am throwing myself upon Stack Exchange's mercy. RPM packagers, please share your secret signing voodoo.

It doesn't seem to be do to with the warnings about stdin being re-opened.

(I'd love to simply not support EL5, but I'm stuck with supporting it for a little longer, as well as newer and saner distros).

Other relevant info:

$ gpg --version
gpg (GnuPG) 1.4.5
...blahcopyrightblah...
Supported algorithms:
Pubkey: RSA, RSA-E, RSA-S, ELG-E, DSA
Cipher: 3DES, CAST5, BLOWFISH, AES, AES192, AES256, TWOFISH
Hash: MD5, SHA1, RIPEMD160, SHA256, SHA384, SHA512, SHA224

$ cat /etc/redhat-release 
CentOS release 5.10 (Final)

Oh, and for bonus WTF points, I generated a throwaway new key directly on the CentOS box, with the passphrase "fred". I can sign stuff with it:

$ gpg -q -a -b --sign -u XXX@XXX.com testfile
You need a passphrase to unlock the secret key for
user: "XXX <XXX@XXX.com>"
1024-bit DSA key, ID 99188B9C, created 2014-08-29

and verify it:

$ gpg -v testfile.asc 
gpg: armor header: Version: GnuPG v1.4.5 (GNU/Linux)
gpg: assuming signed data in `testfile.asc'
gpg: Signature made Fri 29 Aug 2014 08:02:47 AM UTC using DSA key ID 99188B9C
gpg: Good signature from "XXX <XXX@XXX.com>"
gpg: binary signature, digest algorithm SHA1

but rpmsign is being even more insane. With exactly the same passphrase it's rejecting it:

$ rpmsign --define '%_gpg_name XXX@XXX.com'  --resign test.el5.x86_64.rpm
Enter pass phrase: 
Pass phrase check failed

whether typed or copied & pasted. Using rpm as a wrapper instead of rpmsign directly makes no difference.

Update: For new bonus crazy points, on CentOS 6.5 using a 2048 bit DSA key, using a test.rpm that was just compiled using mock within a CentOS 6.5 target mock environment (i.e. with a matching RPM version):

$ rpmsign --define '%_gpg_name 92FB1E62' --resign test.rpm
Enter pass phrase: 
Pass phrase is good.
test.rpm:

$ rpm -v -K test.rpm 
error: skipping package test.rpm with unverifiable V4 signature

Yup – rpmsign just signed the package, then rejected its own signature.

Clearly most people don't have these problems. What am I missing?

Best Answer

It's a cluster of RPM bugs. Not just one bug, or two bugs. A nest of the critters. RPM fails (failed?) to validate signed packages, didn't understand v4 GPG signatures but didn't notice it didn't understand them, didn't understand some key sizes and types but didn't notice it didn't understand that, and also choked on subkeys!

This lifesaving blog entry by Jacob Helwig, as pointed out by a colleague, covers the issues:

You must force GnuPG to use v3 signatures when signing on/for RHEL / CentOS 5 or 6 in your `

%__gpg_sign_cmd %{__gpg} \
    gpg --force-v3-sigs --digest-algo=sha1 --batch --no-verbose --no-armor \
    --passphrase-fd 3 --no-secmem-warning -u "%{_gpg_name}" \
    -sbo %{__signature_filename} %{__plaintext_filename}

because RPM doesn't check the sigversion or validate the signed package after signing it, and these distros contain GPG versions that default to v4 signatures.

You must also generate a 2048 bit signing-only RSA key with no subkeys.

A couple of relevant bugs:

Related Topic