Fedora

Fix RPM “NOKEY” and “does not verify: no signature” Errors on Fedora 45

On Fedora 45, rpm -i refuses any package whose signature it cannot verify. Fedora 44 printed a NOKEY warning and installed the package anyway. Fedora 45 prints the same warning and then stops with does not verify, and nothing gets installed. An unsigned package you built yourself fails the same way, with does not verify: no signature. Old install scripts, Ansible tasks and vendor instructions that call rpm -ivh on a downloaded file break the first time they meet a package whose key is not already imported.

Original content from computingforgeeks.com - post 172308

This guide explains why Fedora 45 rejects these packages and goes through the errors one at a time. It covers the fixes that keep signature checking on: install through dnf, import the vendor’s OpenPGP key with rpmkeys, autosign your own rpmbuild output, and mark a private repository as unsigned. It also shows how to turn the check off per command or system wide, and what that costs you. The outputs below come from a Fedora 45 machine with rpm 6.1 and signature enforcement left at its default, with a Fedora 44 machine alongside as the baseline.

Why rpm refuses the package on Fedora 45

The Enforcing signature checking by default change sets one rpm macro, %_pkgverify_level. On Fedora 45 it moves from digest to all. Under digest, rpm only confirmed that the package was not corrupted. Under all, the package also needs a valid signature from a key that is already in the rpm keyring. Check the value on your machine:

rpm --eval '%_pkgverify_level'

Fedora 45 prints all and Fedora 44 prints digest. The default comes from /usr/lib/rpm/macros, and /etc/rpm/ ships empty, so nothing local overrides it on a fresh install. That one setting changed the following on the two test machines, using the same Google Chrome RPM and the same unsigned test package on both:

ActionFedora 44Fedora 45
rpm -ivh on a signed RPM, key not imported (Chrome)Warns NOKEY, installsWarns NOKEY, refuses
rpm -ivh on an unsigned RPMInstalls silentlyRefuses: no signature
rpmkeys -K on an unsigned RPMdigests OK, exit 0digests SIGNATURES NOT OK, exit 1
dnf install ./file.rpmInstalls a signed RPM, warns it skipped OpenPGP checksInstalls signed or unsigned, warns it skipped OpenPGP checks
dnf from a repo with gpgcheck=0Installs (dnf default)Installs

The rest of the system is unaffected. Updates from Fedora, RPM Fusion and vendor repos still go through dnf, which checks package signatures for every repo set to gpgcheck=1, which is what Fedora, RPM Fusion and most vendor repo files set. The change only reaches tools that call rpm directly or read its verification result, such as rpm -i, rpm -U, rpmkeys -K and scripts built on them. It is also listed in the Fedora 45 release changes, and you hit it right after an upgrade from Fedora 44 if you keep a folder of vendor RPMs around.

Both failures on the Fedora 45 test machine, with the enforcing level that causes them:

Fedora 45 rpm -ivh failing with NOKEY and does not verify no signature errors

The signature errors and what each one means

Three messages cover almost every case. The exact text tells you which fix applies, so read it before you reach for --nosignature.

Error: “does not verify: Header OpenPGP V4 RSA/SHA512 signature, key ID fd533c07c264648f: NOKEY”

The package is signed, but rpm does not have the public key that made the signature. Chrome, RPM Fusion release packages and most vendor downloads hit this one. The fix is to import the right key (Fix 2). The key ID in the message is often a signing subkey rather than the primary key, so it will not match the fingerprint you see after import. The captured output from Chrome:

warning: google-chrome-stable_current_x86_64.rpm: Header OpenPGP V4 RSA/SHA512 signature, key ID fd533c07c264648f: NOKEY
Verifying...                          ########################################
Preparing...                          ########################################
	package google-chrome-stable-154.0.8037.92-1.x86_64 does not verify: Header OpenPGP V4 RSA/SHA512 signature, key ID fd533c07c264648f: NOKEY

Error: “package does not verify: no signature”

The package carries no signature at all. The usual sources are your own rpmbuild output, CI artifacts and small vendors who never sign. No key will fix this. Sign the package (Fix 3), serve it from a repo marked unsigned (Fix 4), or install it through dnf (Fix 1). The verbose check shows digests present and every signature slot empty:

rpmkeys -Kv hello-local-1.0-1.fc45.noarch.rpm

Every signature line reads NOTFOUND. The exit code is 1 on Fedora 45 and was 0 on Fedora 44, which is what breaks CI jobs that gate on rpmkeys -K:

hello-local-1.0-1.fc45.noarch.rpm:
    Header OpenPGP DSA signature: NOTFOUND
    Header OpenPGP RSA signature: NOTFOUND
    Header OpenPGP signature: NOTFOUND
    Header SHA256 digest: OK
    Payload SHA256 digest: OK
    Legacy OpenPGP DSA signature: NOTFOUND
    Legacy OpenPGP RSA signature: NOTFOUND

Error: “OpenPGP check for package … has failed: The package is not signed.”

This one comes from dnf, not rpm. It appears when a repo has gpgcheck=1 but serves unsigned packages, or when you turned on localpkg_gpgcheck and then installed an unsigned local file. The same check on a signed local file whose key is missing fails with The repository does not have any OpenPGP keys configured. instead. Both are covered below.

Fix 1: Install local RPM files with dnf instead of rpm

For a one-off desktop install, replace rpm -ivh with dnf install ./file.rpm. dnf also resolves dependencies, which rpm -i never did. That alone makes Chrome installable on a minimal system, where rpm -i listed 42 missing dependencies on the Fedora 44 test box:

sudo dnf install ./google-chrome-stable_current_x86_64.rpm

The transaction completes, but look at the second to last line. dnf installed the package without checking the signature:

Warning: skipped OpenPGP checks for 1 package from repository: @commandline
Complete!

That is the failure mode of this fix. dnf defaults localpkg_gpgcheck to false, so it trusts any file you pass on the command line, signed or not, with or without a key. The unsigned test package installed the same way. The dnf5daemon backend, which GNOME Software depends on for package installs on Fedora 45, behaved the same way when driven with dnf5daemon-client on the test machine: it installed both the unsigned package and the Chrome RPM with no Google key present. So dnf gets you past the error, but it does not verify anything. Treat a local RPM like a script from the internet and check it yourself before you install it:

rpmkeys -K google-chrome-stable_current_x86_64.rpm

To make dnf enforce signatures on local files, the way rpm now does, add a drop-in file. This is the right setting for servers and build hosts:

printf "[main]\nlocalpkg_gpgcheck=True\n" | sudo tee /etc/dnf/libdnf5.conf.d/80-localpkg-gpgcheck.conf

Confirm that dnf picked it up:

dnf --dump-main-config | grep localpkg

The option now reads as enabled:

localpkg_gpgcheck = 1

With the check turned on, the Chrome RPM failed with The repository does not have any OpenPGP keys configured. until the Google key was imported. After the import it installed with no “skipped OpenPGP checks” warning, which means dnf really verified it this time. If you need to override the check once, --nogpgcheck (an alias for --no-gpgchecks) still works on the command line.

Release packages that you install from a URL follow the same pattern. The RPM Fusion setup command that a lot of old guides still copy fails under rpm:

sudo rpm -ivh https://mirrors.rpmfusion.org/free/fedora/rpmfusion-free-release-45.noarch.rpm

rpm downloads it and rejects it, because the RPM Fusion key is not in the keyring yet:

warning: /var/tmp/rpm-tmp.lu8gge: Header OpenPGP V4 RSA/SHA256 signature, key ID e06f8ecdd651ff2e: NOKEY
Retrieving https://mirrors.rpmfusion.org/free/fedora/rpmfusion-free-release-45.noarch.rpm
Verifying...                          ########################################
Preparing...                          ########################################
	package rpmfusion-free-release-45-0.2.noarch does not verify: Header OpenPGP V4 RSA/SHA256 signature, key ID e06f8ecdd651ff2e: NOKEY

The dnf form installs it, though dnf still reports that it skipped OpenPGP checks for the release package itself, because it came from @commandline. Packages from the new repo are then checked against the key the release package ships, as for any repo with gpgcheck=1. That is the reason the RPM Fusion setup guide uses dnf:

sudo dnf install https://mirrors.rpmfusion.org/free/fedora/rpmfusion-free-release-$(rpm -E %fedora).noarch.rpm

Fix 2: Import the vendor’s OpenPGP key with rpmkeys

This is the proper fix for NOKEY. Once the key is imported, rpm -i works again and actually verifies the package. The risk is importing the wrong key, so match it to the package before you trust it. Start by reading the signature and vendor from the package header:

rpm -qp --qf '%{NAME}: %{RSAHEADER:pgpsig}\n%{VENDOR} | %{PACKAGER}\n' google-chrome-stable_current_x86_64.rpm 2>/dev/null

The package was signed by Google LLC with key ID fd533c07c264648f:

google-chrome-stable: RSA/SHA512, Tue 29 Sep 2026 05:46:17 AM UTC, Key ID fd533c07c264648f
Google LLC | Chrome Linux Team <[email protected]>

Download the vendor’s published key over HTTPS and confirm that it contains that key ID. sq comes from the sequoia-sq package:

sudo dnf install sequoia-sq
curl -fsSL https://dl.google.com/linux/linux_signing_key.pub -o google.pub
sq inspect google.pub | grep -A4 -i fd533c07c264648f

The match is a signing subkey of Google’s certificate, valid until 2028. That confirms this certificate is the one that signed the package:

           Subkey: 0E225917414670F4442C250DFD533C07C264648F
  Public-key algo: RSA
  Public-key size: 4096 bits
    Creation time: 2025-01-07 16:53:01 UTC
  Expiration time: 2028-01-07 16:53:01 UTC (creation time + 2years 11months 29days 15h 50m 24s)

Import it, list the keyring, check the package again and install it:

sudo rpmkeys --import google.pub
rpmkeys --list
rpmkeys -K google-chrome-stable_current_x86_64.rpm
sudo rpm -ivh google-chrome-stable_current_x86_64.rpm

The check now reads digests signatures OK and the install goes through. The same sequence on the test machine, run with the key URL directly:

rpmkeys import of the Google signing key on Fedora 45 followed by a successful rpm install

Two lines in that capture look alarming but are harmless. The import warns about five expired subkeys. That is normal for a long-lived vendor certificate, and the subkey that signed this package is still valid. The can't create keyring lock and key 1 import failed lines at the end come from Chrome’s own post-install script, which tries to import the key while rpm still holds the keyring lock. Fedora 44 printed similar errors against its transaction lock. The script also writes /etc/yum.repos.d/google-chrome.repo with the key URL in gpgkey=, so if you skip the manual import, dnf fetches the key the first time it pulls Chrome from that repo:

Importing OpenPGP key 0xD38B4796:
 UserID     : "Google Inc. (Linux Packages Signing Authority) <[email protected]>"
 Fingerprint: EB4C1BFD4F042F6DDDCCEC917721F63BD38B4796
 From       : https://dl.google.com/linux/linux_signing_key.pub
The key was successfully imported.

When dnf imports a key this way, read the fingerprint it prints before you answer yes. With -y, dnf still prints the key but imports it without asking.

Fix 3: Sign the packages you build with rpm-setup-autosign

This is the fix for your own unsigned builds. rpm on Fedora 45 includes rpm-setup-autosign (in the rpm-build package). It creates a passwordless signing key for your user, and every rpmbuild afterwards signs its output automatically. Run it once as the user who builds packages, not as root:

rpm-setup-autosign

It picked gpg on the test machine, because that is rpm’s default signer. It then printed the import command to run next:

Generating key rpmbuild-mercy@rpm-lab01
Exporting public key (certificate) to /home/mercy/[email protected]
Setting up gpg autosigning in /home/mercy/.rpmmacros
To import this public key (certificate), run:
	sudo rpmkeys --import /home/mercy/[email protected]

The key and the macros went into your home directory. The rpm-setup-autosign man page lists ~/.config/rpm, but the script falls back to your home directory when ~/.config/rpm does not exist and ~/.rpmmacros does, and rpmdev-setuptree creates ~/.rpmmacros. Importing from ~/.config/rpm on this machine failed with import read failed(2), because the file was not there. Always use the exact path the script prints. For the home directory case, as here, that is:

sudo rpmkeys --import ~/rpmbuild-$USER@$(uname -n).asc

If the script wrote to ~/.config/rpm instead, import ~/.config/rpm/rpmbuild-$USER@$(uname -n).asc. To test the setup, the lab used a minimal spec file that packages one shell script. Create it:

vim hello.spec

Paste the spec. Any of your own spec files works the same way:

Name:     hello-local
Version:  1.0
Release:  1%{?dist}
Summary:  Test package for signature checks
License:  MIT
BuildArch: noarch

%description
Minimal package used to test RPM signature enforcement.

%install
mkdir -p %{buildroot}%{_bindir}
printf '#!/bin/sh\necho hello from hello-local\n' > %{buildroot}%{_bindir}/hello-local
chmod 0755 %{buildroot}%{_bindir}/hello-local

%files
%{_bindir}/hello-local

Build it and check the signature. No rpm-sign package or extra flag is needed. The output path follows the package name, version and %{?dist} tag:

rpmbuild -bb hello.spec
rpmkeys -Kv ~/rpmbuild/RPMS/noarch/hello-local-1.0-1.fc45.noarch.rpm

The header now carries an EdDSA signature from the autosign key, verified against the fingerprint that was just imported:

/home/mercy/rpmbuild/RPMS/noarch/hello-local-1.0-1.fc45.noarch.rpm:
    Header OpenPGP V4 EdDSA/SHA512 signature, key fingerprint: 9f7000400c1fe72037562adba79716d49bacce0e: OK
    Header SHA256 digest: OK
    Payload SHA256 digest: OK

The whole flow on the test machine, from key generation to the verified package:

rpm-setup-autosign on Fedora 45 producing an EdDSA signed rpmbuild package that verifies OK

With the signature in place, rpm -ivh installs the package. Import the same .asc file on every machine that installs your builds. The key has no password. Anyone who can read your home directory can sign packages that those machines will trust, so use a dedicated build user, and do not reuse the key for anything you publish.

You can use the same key to sign an unsigned RPM you did not build, such as a vendor download you have checked some other way. This needs the rpm-sign package. Pass the key explicitly: without --key-id, rpmsign stops with You must set "%_openpgp_sign_id" in your macro file:

sudo dnf install rpm-sign
rpmsign --addsign --key-id "$(rpm --eval %_openpgp_autosign_id)" vendor-unsigned.rpm
rpmkeys -K vendor-unsigned.rpm

The re-signed file passes the check and installs with plain rpm:

vendor-unsigned.rpm: digests signatures OK

Fix 4: Serve unsigned packages from a repo marked gpgcheck=0

If you already run an internal repository of unsigned builds, you can leave the packages unsigned. dnf switches off rpm’s check for each package it installs from a repo with signature checking disabled. mock relies on the same mechanism to install packages it has just built. The test used a local repo built with createrepo_c in /srv/localrepo. Create the repo file:

sudo vim /etc/yum.repos.d/localrepo.repo

Add the repository definition. gpgcheck=0 is the line that matters:

[localrepo]
name=Local unsigned packages
baseurl=file:///srv/localrepo
enabled=1
gpgcheck=0

With gpgcheck=1, the same package failed with OpenPGP check for package "hello-local-1.0-1.fc45.noarch" ... from repo "localrepo" has failed: The package is not signed. With gpgcheck=0, it installs with a warning that names the repo:

sudo dnf install hello-local

The transaction completes:

[3/3] Installing hello-local-0:1.0-1.fc 100% |   4.2 KiB/s | 300.0   B |  00m00s
Warning: skipped OpenPGP checks for 1 package from repository: localrepo
Complete!

Keep gpgcheck=0 for repos you control on a network you trust. For anything else, sign the packages with Fix 3 and serve the public key in gpgkey=.

Last resort: skip or revert rpm signature checking

Two switches turn the check off. Use the per-command one for a single package you have already verified:

sudo rpm -ivh --nosignature hello-local-1.0-1.fc45.noarch.rpm

The system-wide switch restores the Fedora 44 behavior for every rpm call on the machine. The Fedora change page documents it for workflows where signing is not possible, such as a build container that installs its own freshly built packages:

echo '%_pkgverify_level digest' | sudo tee /etc/rpm/macros.verify

rpm reads the file at once. rpm --eval '%_pkgverify_level' returned digest, and the unsigned package installed with no error. The macro accepts four levels, documented in rpm’s upstream macros file:

LevelWhat rpm requires before installing
all (Fedora 45 default)Valid digests and a valid signature
signatureA valid signature
digest (Fedora 44 behavior)Valid digests only
noneNothing (traditional rpm behavior)

Do not leave digest in place on a workstation or a server that installs anything from the internet. Digests only prove the file is intact. Without the signature check, rpm installs a tampered package as root as long as the attacker rebuilt it with valid digests. Undo it by deleting the file:

sudo rm /etc/rpm/macros.verify

Manage the rpm keyring on Fedora 45

rpmkeys is now the main tool for the keyring. --list prints each key’s fingerprint and user ID, which is much easier to read than the old gpg-pubkey package names. The keys are still stored in the rpm database (rpm’s default %_keyring is rpmdb), so rpm -qa gpg-pubkey keeps working for existing scripts. List what the machine trusts:

rpmkeys --list

A fresh install trusts only the Fedora 45 key. Every other line got there through an import:

4f50a6114cd5c6976a7f1179655a4b02f577861e Fedora (45) <[email protected]> public key
eb4c1bfd4f042f6dddccec917721f63bd38b4796 Google Inc. (Linux Packages Signing Authority) <[email protected]> public key
9f7000400c1fe72037562adba79716d49bacce0e <rpmbuild-mercy@rpm-lab01> public key

Remove a key you no longer trust by its fingerprint, and export one to inspect or copy to another machine:

sudo rpmkeys --erase eb4c1bfd4f042f6dddccec917721f63bd38b4796
rpmkeys --export 4f50a6114cd5c6976a7f1179655a4b02f577861e | sq inspect

Fedora’s own key files have also moved. /etc/pki/rpm-gpg/ is empty on Fedora 45, and the distribution keys are in /usr/share/pki/rpm-gpg/, next to the repo files in /usr/share/dnf5/repos.d/, per the Fedora change that relocated them. Third-party repo files still land in /etc/yum.repos.d/, as google-chrome.repo did here. The dnf5 cheat sheet covers the repo side of that layout.

Checklist before you trust a local RPM on Fedora 45

Run through this list every time a package arrives as a file instead of from a repo. Signature enforcement only protects you if you do not work around it without checking first.

  1. Run rpmkeys -Kv on the file. OK means a key you already trust signed it. NOKEY means you need the vendor’s key. NOTFOUND on every signature line means the package is unsigned.
  2. For NOKEY, read %{RSAHEADER:pgpsig} and %{VENDOR} from the header. Download the vendor’s key over HTTPS from the vendor’s own domain.
  3. Confirm the key ID from the error appears in sq inspect output for that key before you run rpmkeys --import.
  4. For packages you build yourself, use rpm-setup-autosign with a dedicated build user, and import its public key only on the machines that install those builds.
  5. Set localpkg_gpgcheck=True on servers, so that dnf install ./file.rpm stops skipping the check.
  6. Keep gpgcheck=0 only for internal repos you control, and never use /etc/rpm/macros.verify as a shortcut on a machine that installs outside software.
  7. Audit rpmkeys --list from time to time and erase keys for vendors you no longer install from.

The same rules apply to the other Fedora 45 changes that affect third-party software. The Fedora 45 post-install checklist covers the repos and codecs most desktops add next, and the Fedora hardening guide picks up where this one stops.

Keep reading

Enable RPM Fusion and Install Multimedia Codecs on Fedora 45 / 44 / 43 Fedora Enable RPM Fusion and Install Multimedia Codecs on Fedora 45 / 44 / 43 Harden Fedora 45 / 44 for Desktop and Server: Complete Guide Fedora Harden Fedora 45 / 44 for Desktop and Server: Complete Guide Things to Do After Installing Fedora 44 Workstation Fedora Things to Do After Installing Fedora 44 Workstation Fedora 45 kmscon Console: Fonts, Keymaps and Reverting to fbcon Fedora Fedora 45 kmscon Console: Fonts, Keymaps and Reverting to fbcon Install COSMIC Desktop on Fedora: Spin, Atomic or dnf group Desktop Install COSMIC Desktop on Fedora: Spin, Atomic or dnf group Btrfs Snapshots and Rollback with Snapper on Fedora 45 / 44 Fedora Btrfs Snapshots and Rollback with Snapper on Fedora 45 / 44

Leave a Comment

Press ESC to close