rpm-software-management / rpm

The RPM package manager
http://rpm.org
Other
497 stars 359 forks source link

Importing a key has no verbosity information, unhelpful error message #1974

Closed DaveWK closed 2 years ago

DaveWK commented 2 years ago

I am attempting to import a repo key:

[root@c08aac51c007 /]# rpm --import gpg.key 
error: gpg.key: key 1 import failed.
[root@c08aac51c007 /]# rpm -v --import gpg.key 
error: gpg.key: key 1 import failed.

Where gpg.key is a local key. This also happens with remote URLs. I would have expected that it actually gives me an indication what the problem with the key is, or at least give me a hint what process/helper to check to further debug..

I am not particularly interested in why this particular key is failing (I assume it's the subkey enforcement changes) but without any indication for a reason, it's a bad UX.

DemiMarie commented 2 years ago

This also happens with remote URLs.

Importing a key from a remote URL is a bad idea. Generally, one should only import keys that are the output of gpg2 --export-options export-minimal --export --armor -- FINGERPRINT or similar.

DemiMarie commented 2 years ago

I am not particularly interested in why this particular key is failing (I assume it's the subkey enforcement changes) but without any indication for a reason, it's a bad UX.

Can you do a gpg --list-packets on that key and paste the results? Because I suspect I know what is going on here: RPM cannot handle keys with revoked subkeys.

teythoon commented 2 years ago

Can you do a gpg --list-packets on that key and paste the results?

Or use https://dump.sequoia-pgp.org/ for better readability.

DaveWK commented 2 years ago

@DemiMarie totally agree that its reckless to be importing keys via URL, thankfully there's some (hopefully functioning properly) validation going on here that just needs to have it's output be better exposed to help end users understand why it deems their key invalid

if you want to reproduce this bug on your own, the key is actually public, and for grafana's rpm repo, key is at: https://packages.grafana.com/gpg.key for my tests I am using the centos 9 stream container from quay.io/centos/centos:stream9

as for output:

Public-Key Packet, old CTB, 269 bytes
    Version: 4
    Creation time: 2017-01-24 13:57:38 UTC
    Pk algo: RSA (Encrypt or Sign)
    Pk size: 2048 bits
    Fingerprint: 4E40DDF6D76E284A4A6780E48C8C34C524098CB6
    KeyID: 8C8C34C524098CB6

User ID Packet, old CTB, 26 bytes
    Value: Grafana <info@grafana.com>

Signature Packet, old CTB, 312 bytes
    Version: 4
    Type: PositiveCertification
    Pk algo: RSA (Encrypt or Sign)
    Hash algo: SHA1
    Hashed area:
      Signature creation time: 2017-01-24 13:57:38 UTC
      Key flags: CS
      Symmetric algo preferences: AES256, AES192, AES128, CAST5, TripleDES
      Hash preferences: SHA256, SHA1, SHA384, SHA512, SHA224
      Compression preferences: Zlib, BZip2, Zip
      Features: MDC
      Keyserver preferences: no modify
    Unhashed area:
      Issuer: 8C8C34C524098CB6
    Digest prefix: 1C49
    Level: 0 (signature over data)

Public-Subkey Packet, old CTB, 269 bytes
    Version: 4
    Creation time: 2017-01-24 13:57:38 UTC
    Pk algo: RSA (Encrypt or Sign)
    Pk size: 2048 bits
    Fingerprint: 0D224E82057BCEE1321424B1CA6D481DBD044C76
    KeyID: CA6D481DBD044C76

Signature Packet, old CTB, 287 bytes
    Version: 4
    Type: SubkeyBinding
    Pk algo: RSA (Encrypt or Sign)
    Hash algo: SHA1
    Hashed area:
      Signature creation time: 2017-01-24 13:57:38 UTC
      Key flags: EtEr
    Unhashed area:
      Issuer: 8C8C34C524098CB6
    Digest prefix: D64B
    Level: 0 (signature over data)
DemiMarie commented 2 years ago

@DaveWK please let Grafana know that they need to re-sign their key with a stronger hash algorithm.

DaveWK commented 2 years ago

Thanks, but my issue is that rpm --import should let me know that the reason it rejected the key is because the hash algorithm was too weak, not specifically my problem with grafana's key

DemiMarie commented 2 years ago

As a general rule of thumb, I recommend always importing keys into GPG or Sequoia and exporting them from there by fingerprint. RPM’s OpenPGP implementation is extremely barebones, whereas GPG and Sequoia will give much better error messages.

DaveWK commented 2 years ago

Thanks, I assume the key strength change is fairly new, and that a lot of people will be confused by the current state of the output and verbosity. Is it possible to add the validation parameters being used (including key strength) in the verbosity output so people know things like what the minimum strength requirement is? Ideally it would tell me the reason it rejected the key, but if the problem is the OpenPGP implementation is very barebones, and doesn't include a reason, it would be nice to know what criteria is being used by the caller the user can investigate if the reason is because the key is completely invalid, or just too weak.

DemiMarie commented 2 years ago

That is an interesting idea which I had not considered.

nwalfield commented 2 years ago

I've created a proof of concept of how we might communicate that a certificate is invalid or has issues. This is based on the Sequoia port (https://github.com/rpm-software-management/rpm/issues/1978). The modifications to the Sequoia backend for rpm is here: https://gitlab.com/sequoia-pgp/rpm-sequoia/-/tree/neal/linter .

To see how this looks, I've used a few certificates from the Sequoia test suite. Here the output, which I think is self explanatory. Nevertheless: the basic idea is: flag certificates and subkeys that are revoked, expired, or unusable (no binding signature, bad algorithm, etc).

$ rpm --import bad-subkey-keyring.pgp
Certificate 9B7DD433F254904A:
  Policy rejects subkey 7223B56678E02528: No binding signature at time 2022-03-29T11:34:15Z
  Policy rejects subkey C2B819056C652598: No binding signature at time 2022-03-29T11:34:15Z
  Subkey 88DC7E33385F791D is expired: The subkey is not live
  Policy rejects subkey A3506AFB820ABD08: No binding signature at time 2022-03-29T11:34:15Z
  Certificate does not have any usable signing keys
Certificate AACB3243630052D9:
  The certificate is expired: The primary key is not live
error: bad-subkey-keyring.pgp: key 1 import failed.
$ rpm --import peter-expired-backsig.pgp
Certificate 251C20A67D942D45:
  Policy rejects subkey CB4F47D30C8C9CE1: Expired on 2020-05-08T05:11:51Z
  Certificate does not have any usable signing keys
$ rpm --import sha-mbles.alice.asc
Certificate 9CD08D5B168087E2:
  Policy rejects 9CD08D5B168087E2: No binding signature at time 2022-03-29T11:34:15Z
error: sha-mbles.alice.asc: key 1 import failed.

I look forward to feedback.

DaveWK commented 2 years ago

@nwalfield This looks really good on handling the subkey case -- thanks! Is there some way to also handle the case if the key is valid, but the hash algorithm is took weak, in my example here the key is valid but does not meet the strength requirements (which as I understand it were recently changed)

nwalfield commented 2 years ago

The proposed patch handles weak hash algorithms as well. In that case, the binding signature will be considered invalid and will be ignored and the error message will be something like: Policy rejects subkey 7223B56678E02528: No binding signature at time XXX.

sq-keyring-linter would give even more details and it has an option to fix the key. See this comment.

DaveWK commented 2 years ago

@nwalfield Excellent! Thanks so much! I think this will help out a lot with people that run into the new changes in requirements.