RHEL 10 RPM Signing: Sequoia PGP, RPMv6 and PQC

Tested on Red Hat Enterprise Linux 10.2 (Coughlan)
Package rpm-4.19.1.1-23.el10.x86_64
rpm-sequoia-1.10.1.1-2.el10.x86_64
sequoia-sq-1.3.1.1-1.el10.x86_64
rpm-sign-4.19.1.1-23.el10.x86_64
Applies to RHEL 10.0+ for Sequoia verification; RHEL 10.1+ for native RPMv6 signature support; RHEL 9.7+ can verify RPMv6 signatures with the documented multisig / pqrpm path
Privilege sudo to install packages and enable Sequoia signing macros; normal user for key generation and rpmsign once macros and keys are in place
Scope What changed in RPM package signing and verification on RHEL 10 versus 10.1, how Sequoia PGP fits in, how to create and verify RPMv6 signatures (including multiple signatures and hybrid PQC), and how to keep RPMv4 compatibility for older systems. Does not cover TLS or SSH post-quantum crypto.
Related guides Post-quantum cryptography in Linux
RPM command cheat sheet
DNF command cheat sheet
Download RPM packages with dependencies
RPM vs DEB packages
Short on time?Beta Get the gist of this 23-minute read in seconds, then ask follow-up questions

In this article we will explain what changed in RPM package signing on RHEL 10, then show how to read signature output and how to sign a package yourself when you need that workflow.

If you only install software with dnf, you can stop after the first few sections. The later labs are for people who build or resign packages. I ran every retained command on RHEL 10.2 with RPM 4.19.1.1.

NOTE
RHEL 10.1's RPMv6 and OpenPGP v6 verification support is not the same thing as the Sequoia signing integration. The macros.rpmsign-sequoia workflow used later in this article to make rpmsign call Sequoia remains a Technology Preview in RHEL 10.2. Use that signing path for evaluation and pipeline planning; check current Red Hat documentation before production signing.
If you came here to… Start here
Understand what changed on RHEL 10 / 10.1 What changed… and the 10.0 vs 10.1 table
Read a confusing rpmkeys -Kv line Verify an existing RPM signature
Learn what “RPMv6 signature” means What is an RPMv6 signature?
Sign a package (RSA, multiple keys, or PQC) Prepare a test RPM…
Verify RPMv6 signatures and trust rules How to Verify RPMv6 Signatures on RHEL 10
Keep older RHEL hosts working Keep an RPMv4 signature… and Compatibility

What changed in RPM package signing on RHEL 10?

RHEL 10 changed the engine that checks package signatures. The older OpenPGP parser inside RPM was replaced with Sequoia PGP (rpm-sequoia). Your install command is the same. The library behind “is this package signature OK?” is what changed.

RHEL 10.1 builds on that with new signature formats and algorithms:

  • RPMv6 signatures (a newer way to store signatures inside an RPM — not a claim that the whole package manager is “RPM 6”)
  • Multiple OpenPGP signatures in one RPM
  • OpenPGP v6 signatures (the newer OpenPGP standard, RFC 9580)
  • Post-quantum and hybrid signatures such as ML-DSA-87+Ed448
IMPORTANT
These changes affect how RPM packages are signed and verified. They do not change the normal dnf install workflow for ordinary users installing correctly signed RHEL packages.

Red Hat’s own wording for the 10.1 feature is that RHEL 10.1 introduces support for RPMv6 signatures. Older blog posts sometimes say “RPM v6” as if your installed rpm binary jumped to major version 6. That is misleading. On RHEL 10.2, rpm --version still reports RPM 4.19.x while RPMv6 signatures work.


RHEL 10 vs RHEL 10.1 RPM signing changes

Use this table to separate what arrived with RHEL 10.0 from what RHEL 10.1 added:

Feature RHEL 10.0 RHEL 10.1+
Sequoia PGP used for RPM verification Yes Yes
Traditional RPMv4 signatures Yes Yes
RPMv6 signatures No native support Yes
Multiple RPMv6 signatures No Yes
OpenPGP v6 signature verification No Yes, through updated rpm-sequoia
PQC RPM verification Not in the 10.1 form Yes
Sequoia-based RPM signing (macros.rpmsign-sequoia) Technology Preview Technology Preview

Sequoia verification shipped with RHEL 10.0; RPMv6/PQC verification and multi-signature are the 10.1 additions; signing via Sequoia macros stays TP.


How RPM package signing works (quick picture)

Here is the idea in plain language before the labs.

A vendor builds an .rpm file, then signs it with a private key. For a vendor package to verify as trusted, the system must have the corresponding public signing certificate. RHEL already includes the keys needed for official Red Hat packages; third-party or locally signed packages require their signing certificates to be imported or referenced separately. When you install or run rpmkeys -Kv, RPM checks: “Was this package signed by a key I trust, and was the file altered after signing?”

  Vendor                     Package file                 Your RHEL host
  ┌──────────────┐           ┌─────────────────┐         ┌──────────────────────┐
  │ Private key  │  signs ►  │  name.rpm        │  verify │ rpm / dnf / rpmkeys  │
  │ (kept secret)│           │  + signature(s) │  ◄───── │ + trusted public cert│
  └──────────────┘           └─────────────────┘         └──────────────────────┘

Three names show up a lot in this article. Keep them separate:

  • RPM — the package format and the rpm / dnf tools that install it
  • OpenPGP — the signature technology (you may still hear people say “GPG key”)
  • Sequoia PGP — the library RHEL 10 uses to check those OpenPGP signatures

Think of Sequoia as a newer, maintained OpenPGP engine. It happens to be written in Rust, but you interact with it as a package (rpm-sequoia) and optionally as a command (sq), not as a Rust project. RPM still asks whether it trusts the key that signed the package; Sequoia is the component that reads the signature bytes and answers. Newer signature types (OpenPGP v6, hybrid PQC) are much easier to support on that engine. For day-to-day installs, Sequoia runs under the hood. You reach for the sq CLI mainly when you create keys or sign packages yourself.

You do not need to memorize algorithm names to install packages. You need them when you read new signature lines or build a signing pipeline.


Check the RPM and Sequoia packages on RHEL 10

Confirm the RPM version and which Sequoia-related packages are installed. The RPM command cheat sheet covers everyday query flags if you need a wider reference beyond signing:

bash
rpm --version

On RHEL 10.2:

output
RPM version 4.19.1.1

That string is the RPM package manager version. It can report 4.19.x even when the host verifies RPMv6 signatures.

Query the packages this guide uses:

bash
rpm -q rpm rpm-sequoia sequoia-sq rpm-sign

Sample output from the lab:

output
rpm-4.19.1.1-23.el10.x86_64
rpm-sequoia-1.10.1.1-2.el10.x86_64
sequoia-sq-1.3.1.1-1.el10.x86_64
rpm-sign-4.19.1.1-23.el10.x86_64

Roles of those packages:

  • rpm — the RPM package manager
  • rpm-sequoia — OpenPGP verification backend used by RPM
  • sequoia-sq — Sequoia command-line tool (sq) for creating and managing OpenPGP keys
  • rpm-sign — provides rpmsign and the Sequoia signing macro template

rpm-sequoia is present for verification on a normal RHEL 10 install. sequoia-sq and rpm-sign are not always installed until you need to create keys or sign packages. Install them with DNF when you start a signing lab:

bash
sudo dnf install sequoia-sq rpm-sign

On this host both packages were already present, so DNF reported nothing to do. If yours are missing, the transaction installs them from BaseOS / AppStream.

Confirm the CLI is available:

bash
sq version
output
sq 1.3.1
using sequoia-openpgp 2.0.0
with cryptographic backend OpenSSL 3.5.5 27 Jan 2026

That line confirms Sequoia is using the system OpenSSL backend, which matters later for FIPS notes.


Verify an existing RPM signature

For most administrators, verification is the first useful step. You do not need to create a signing key just to inspect an RPM.

Download a signed RHEL package:

bash
dnf download --destdir=/tmp bash

Then verify the file (adjust the filename if your mirror returns a different build):

bash
rpmkeys -Kv /tmp/bash-5.2.26-6.el10.x86_64.rpm
output
/tmp/bash-5.2.26-6.el10.x86_64.rpm:
    Header V4 RSA/SHA256 Signature, key ID fd431d51: OK
    Header SHA256 digest: OK
    Header SHA1 digest: OK
    Payload SHA256 digest: OK
    V4 RSA/SHA256 Signature, key ID fd431d51: OK
    MD5 digest: OK

Read that output in four parts:

  • Signature type — here a traditional V4 RSA signature on the package header (and another on the payload)
  • Key ID — short identifier for the Red Hat signing certificate your system already trusts
  • OK — that signature matched a trusted certificate
  • Digest lines — checksums that the file contents were not corrupted (these can pass even when no signature exists)

rpm -Kv is the same check when you prefer the older spelling. For the rest of this article I use rpmkeys -Kv.

If a package was never signed, you only see digest lines. That is normal for a local test build, not for Red Hat BaseOS packages:

bash
rpmkeys -Kv ~/rpm-sign-lab/work/glc-hello-unsigned.rpm
output
/root/rpm-sign-lab/work/glc-hello-unsigned.rpm:
    Header SHA256 digest: OK
    Header SHA1 digest: OK
    Payload SHA256 digest: OK
    MD5 digest: OK

Digest checks confirm that package contents match the checksums stored in the RPM. Signature checks add authenticity by proving that the signed package data matches a trusted signing key. Both matter, but they are not the same check.


What is an RPMv6 signature?

An RPMv6 signature is the newer RPM signature format that allows multiple OpenPGP signatures to be associated with one package. It does not mean your installed RPM package manager is version 6.

Analogy that helps:

  • RPMv4 signature — one traditional seal on the package
  • RPMv6 signatures — a newer seal area that can hold several seals at once (RSA today, hybrid PQC tomorrow, or two different organizational keys)

Key points:

  • Older RHEL releases mainly understand the RPMv4 seal
  • RHEL 10.1 and later understand the RPMv6 seal area natively with system rpm / rpmkeys
  • Existing RPMv4-only packages keep working. If no RPMv6 seal is present, RPM still checks the RPMv4 path

RPMv4 vs RPMv6 signatures

Capability RPMv4 signature RPMv6 signature
Supported on older RHEL releases Yes (broadly) Depends on release and tooling
Multiple signatures One traditional RPMv4 signature Multiple RPMv6 signatures
PQC / OpenPGP v6 use Limited Designed for newer signature types
RHEL 10.1+ verification Used only when no RPMv6 signature exists Used when present; legacy RPMv4 signature is ignored

Important RHEL 10.1 behavior:

IMPORTANT
If RPMv6 signatures are present, RHEL 10.1 and later verify the RPMv6 signatures and ignore the legacy RPMv4 signature slot. If no RPMv6 signature is present, RPM falls back to RPMv4 verification. Every RPMv6 signature that is present must verify for the package to be trusted.

One easy mix-up: after rpmsign --addsign --rpmv6 with an RSA key, rpmkeys -Kv may still print Header V4 RSA/SHA512 Signature. Here V4 is the OpenPGP key/signature generation (RFC 4880 style RSA). The --rpmv6 flag is about which RPM seal area stored it. Different layers, same output line. PQC keys make this clearer because the line says Header V6 ML-DSA-87+Ed448/... instead.


Prepare a test RPM and enable Sequoia signing

From here on, the article is a signing lab. Skip this block if you only needed to read signatures.

You need an unsigned .rpm you control. I built a tiny noarch package named glc-hello with rpm-build under ~/rpm-sign-lab. Any local unsigned package works. Do not resign official Red Hat packages for practice; use your own test build.

Signing also needs two extra pieces of configuration:

  1. Tell RPM to call Sequoia (sq) instead of GnuPG when signing
  2. Tell RPM which key fingerprint to use

Enable the Technology Preview Sequoia signing macros by copying the template into /etc/rpm/:

bash
sudo cp /usr/share/doc/rpm/macros.rpmsign-sequoia /etc/rpm/

That file points %__gpg at /usr/bin/sq and defines the Sequoia sign command that rpmsign runs. Without it, RPM still expects the traditional GnuPG signing path.

Leave the fingerprint step until after you generate a key in the next section. Sequoia needs an exact fingerprint (or key ID), not an email address match the way GnuPG often allows.


Sign an RPM with an RPMv6 signature

Generate a classical OpenPGP v4 RSA key first (no PQC yet). --without-password keeps the lab non-interactive. Protect production signing keys with a password or an HSM workflow instead.

bash
sq key generate --own-key --without-password --expiration=never \
  --cannot-authenticate --cannot-encrypt \
  --email vendor-rsa@example.com \
  --name "Vendor Inc RSA" \
  --cipher-suite rsa4k \
  --profile rfc4880

Trimmed output:

output
Transferable Secret Key.

      Fingerprint: D3B1F1B0BD1B03D9755BCDE637D7BA4EF996387C
  Public-key algo: RSA
  Public-key size: 4096 bits
...
           Subkey: 38CBD7B21D290512D8D79BD604D2D9B08FE8B3A4
  Public-key algo: RSA
...
        Key flags: signing

Copy the primary fingerprint into your user RPM macros. On RHEL 10.1+ with macros.rpmsign-sequoia, that hook is %_gpg_name:

bash
mkdir -p ~/.config/rpm && printf '%s\n' '%_gpg_name D3B1F1B0BD1B03D9755BCDE637D7BA4EF996387C' > ~/.config/rpm/macros

Use your fingerprint from sq key generate or sq key list, not the lab value above, unless you are following this exact example. Fedora or upstream RPM docs may show %_openpgp_sign sq and %_openpgp_sign_id instead. Same idea, different macro names.

Sign with --rpmv6:

bash
rpmsign --addsign --rpmv6 ~/rpm-sign-lab/work/glc-hello-rsa1.rpm

rpmsign reprints the path and exits silently on success. Export the public certificate so install hosts can trust it:

bash
sq cert export --cert D3B1F1B0BD1B03D9755BCDE637D7BA4EF996387C > ~/rpm-sign-lab/work/RPM-PGP-KEY-VENDOR-RSA

Import that certificate into the RPM keyring. Without this step, verification reports NOKEY even though the signature is present:

bash
rpmkeys --import ~/rpm-sign-lab/work/RPM-PGP-KEY-VENDOR-RSA

rpmkeys --import exits quietly on success. Check the package again and look for an OK signature line:

bash
rpmkeys -Kv ~/rpm-sign-lab/work/glc-hello-rsa1.rpm
output
/root/rpm-sign-lab/work/glc-hello-rsa1.rpm:
    Header V4 RSA/SHA512 Signature, key ID 8fe8b3a4: OK
    Header SHA256 digest: OK
    Header SHA1 digest: OK
    Payload SHA256 digest: OK
    MD5 digest: OK

Compared with an ordinary RPMv4-only habit, two things changed: you passed --rpmv6, and the signature was produced through Sequoia (sq) rather than GnuPG. The V4 RSA/SHA512 label is the OpenPGP algorithm style. The short key ID 8fe8b3a4 matches the signing subkey from the key listing.


Add multiple signatures to the same RPM

RPMv6 allows more than one OpenPGP signature on the same package. Sign once with the first key, then point %_gpg_name at a second fingerprint and sign again.

Common reasons to carry more than one signature:

  • Carry classical and PQC signatures together during the transition so the package is protected by more than one algorithm family. RHEL 10.1 still requires every RPMv6 signature present to verify successfully.
  • Keep an RPMv4-compatible classical signature so older verifiers can still check the package.
  • Use more than one organizational signing key when your process requires it

One bad RPMv6 signature fails the whole check even if another signature looks fine.

RHEL 10.1 also changed rpmsign --addsign behavior for this multi-signature world: adding a signature no longer removes existing signatures. That is what makes repeated rpmsign --addsign --rpmv6 useful. An identical signature is not re-added. Use --resign when you intentionally want to replace all existing signatures.

I generated a second RSA key (vendor-rsa2@example.com, fingerprint F73FF73D5A52601AA8C7AFFE924A1CE17019752C), updated %_gpg_name, and ran:

bash
rpmsign --addsign --rpmv6 ~/rpm-sign-lab/work/glc-hello-multi.rpm

After importing both certificates:

bash
rpmkeys -Kv ~/rpm-sign-lab/work/glc-hello-multi.rpm
output
/root/rpm-sign-lab/work/glc-hello-multi.rpm:
    Header V4 RSA/SHA512 Signature, key ID d4ba0741: OK
    Header V4 RSA/SHA512 Signature, key ID 8fe8b3a4: OK
    Header SHA256 digest: OK
    Header SHA1 digest: OK
    Payload SHA256 digest: OK
    MD5 digest: OK

Two signature lines with different key IDs means two RPMv6 signatures are present. Both must show OK. If either certificate is missing from the keyring, that line becomes NOKEY and verification fails overall.


How to Verify RPMv6 Signatures on RHEL 10

You already imported certificates during the labs. This section is the general rule to remember later, plus how RHEL 10.1 chooses which signatures to check.

Import the signing certificate into the RPM keyring:

bash
rpmkeys --import RPM-PGP-KEY-VENDOR

Then check the package:

bash
rpmkeys -Kv package.rpm

Verification succeeds only when every required signing certificate is trusted. For classical plus PQC RPMv6 signatures, import every certificate that produced a signature line. Repository configs can list multiple gpgkey= URLs the same way.

How to read the result lines:

  • OK — that signature matched a trusted certificate in the RPM keyring
  • NOKEY — a signature is present, but the matching public certificate is not imported yet
  • Multiple signature lines — each line is one RPMv6 signature; on RHEL 10.1+ every one of them must succeed when RPMv6 signatures are present

Older GnuPG-based tooling may not understand OpenPGP v6/PQC key material. For example, Red Hat documents this limitation for Ansible's GnuPG-backed rpm_key handling on RHEL 10.1. Use RPM/Sequoia-aware tooling (rpmkeys --import, Sequoia) for these newer certificates.

How RHEL 10.1 chooses which signature to verify

RPM contains RPMv6 signature(s)

RHEL 10.1 and later verify the RPMv6 signatures and ignore the legacy RPMv4 signature slot. Every RPMv6 signature present must succeed. That is why a classical-plus-PQC package shows both the ML-DSA and RSA lines as RPMv6-era verification results, not as optional extras.

RPM contains no RPMv6 signature

RPM falls back to the RPMv4 signature. The stock bash package earlier in this article is that path: traditional V4 RSA lines, no RPMv6 container required.


What is OpenPGP v6?

OpenPGP is the signature technology RPM uses (the “GPG key” people talk about for repos). OpenPGP has generations, just like TLS versions:

  • OpenPGP v4 (older, still common) — selected in Sequoia with --profile rfc4880
  • OpenPGP v6 (newer, RFC 9580) — selected with --profile rfc9580

RHEL 10.1’s rpm-sequoia stack can verify OpenPGP v6 signatures. The classical RSA lab above used v4. The PQC lab below uses v6 because that is what the hybrid post-quantum key profile needs.

Remember the naming trap: OpenPGP v6 (crypto standard) is not the same phrase as RPMv6 signature (how RPM stores seals on the package).


What are post-quantum RPM signatures?

Some public-key algorithms used today may become weaker if large quantum computers arrive. Package signatures made now may still need to verify years later on long-lived systems, so vendors are adding stronger options early.

RHEL 10.1 supports post-quantum signatures for RPM packages. Red Hat’s documented example is a hybrid signature: ML-DSA-87 combined with Ed448. “Hybrid” means one seal uses both a newer post-quantum algorithm and a classical one, so you are not betting on only one side during the transition. That is stronger future planning, not a claim that packages are “quantum proof.”

You do not need the full algorithm paper to use the lab. Treat mldsa87 as “the hybrid key type Red Hat shows for this workflow.”

For broader Linux PQC context outside RPM (TLS, SSH, OpenSSL labs), see post-quantum cryptography in Linux.


Create a PQC OpenPGP key with Sequoia PGP

Generate a hybrid ML-DSA-87+Ed448 key with the RFC 9580 profile:

bash
sq key generate --own-key --without-password --expiration=never \
  --cannot-authenticate --cannot-encrypt \
  --email vendor-pqc@example.com \
  --name "Vendor Inc PQC" \
  --cipher-suite mldsa87 \
  --profile rfc9580

Trimmed output from the lab:

output
Transferable Secret Key.

      Fingerprint: 027BDCED71FE7FAA764F062420A17D1C810AF17081B02F47DC3E5ADEB9B3E81C
  Public-key algo: ML-DSA-87+Ed448
...
           Subkey: 271374C4DEA41AA1120020E04A2A177CFD5D88277D08A8D8C05B886E9C396280
  Public-key algo: ML-DSA-87+Ed448
...
        Key flags: signing

Useful options in that command:

  • --cipher-suite mldsa87 — hybrid key type Red Hat documents for this RPM signing example
  • --profile rfc9580 — OpenPGP v6 key material
  • --cannot-authenticate / --cannot-encrypt — signing-only key; skip encryption features you do not need for RPM
  • --expiration=never — lab convenience; production keys usually expire on a schedule

List keys when you need fingerprints:

bash
sq key list

Configure RPM to sign with the Sequoia key

Point RPM at the PQC fingerprint the same way as the RSA key. Overwrite the earlier %_gpg_name line so only the PQC key is selected:

bash
printf '%s\n' '%_gpg_name 027BDCED71FE7FAA764F062420A17D1C810AF17081B02F47DC3E5ADEB9B3E81C' > ~/.config/rpm/macros

If /etc/rpm/macros.rpmsign-sequoia is already in place, that file still redirects signing through sq. The user macro only chooses which certificate signs.

If you read older notes online, you may see two styles:

  • RHEL Technology Preview: macros.rpmsign-sequoia plus %_gpg_name (this lab)
  • Fedora / upstream RPM: %_openpgp_sign sq and %_openpgp_sign_id

Test the macros on your release instead of copying a RHEL 10.0 snippet blindly onto 10.1 or 10.2.


Sign an RPM with a post-quantum signature

Sign with the PQC key and --rpmv6:

bash
rpmsign --addsign --rpmv6 ~/rpm-sign-lab/work/glc-hello-pqc.rpm

Export the PQC certificate for distribution to verify hosts:

bash
sq cert export --cert 027BDCED71FE7FAA764F062420A17D1C810AF17081B02F47DC3E5ADEB9B3E81C > ~/rpm-sign-lab/work/RPM-PGP-KEY-VENDOR-PQC

Before the certificate is trusted, rpmkeys still sees the signature but cannot validate the signer:

bash
rpmkeys -Kv ~/rpm-sign-lab/work/glc-hello-pqc.rpm
output
/root/rpm-sign-lab/work/glc-hello-pqc.rpm:
    Header V6 ML-DSA-87+Ed448/SHA512 Signature, key ID dea41aa1: NOKEY
    Header SHA256 digest: OK
    Header SHA1 digest: OK
    Payload SHA256 digest: OK
    MD5 digest: OK

Import the certificate into the RPM keyring:

bash
rpmkeys --import ~/rpm-sign-lab/work/RPM-PGP-KEY-VENDOR-PQC

Run the same check again. The algorithm line should flip from NOKEY to OK:

bash
rpmkeys -Kv ~/rpm-sign-lab/work/glc-hello-pqc.rpm
output
/root/rpm-sign-lab/work/glc-hello-pqc.rpm:
    Header V6 ML-DSA-87+Ed448/SHA512 Signature, key ID dea41aa1: OK
    Header SHA256 digest: OK
    Header SHA1 digest: OK
    Payload SHA256 digest: OK
    MD5 digest: OK

How to read that signature line:

  • V6 — OpenPGP v6 signature packet
  • ML-DSA-87+Ed448 — hybrid post-quantum plus classical algorithms
  • SHA512 — hash used for the signature
  • key ID dea41aa1 — short ID derived from the signing material (matches the subkey listing above)
  • OK — the trusted certificate verified the signature

Red Hat’s developer write-up shows a similar line with an OpenPGP prefix and a full fingerprint. RHEL 10.2’s rpmkeys on this host prints the shorter Header V6 … Signature, key ID … form. The algorithm string is the part to match.


Keep an RPMv4 signature for older RHEL systems

One RPM can carry:

  • an RPMv4-compatible signature for older verifiers
  • one or more RPMv6 signatures for newer verifiers

Red Hat recommends keeping a compatible RPMv4 signature before adding PQC RPMv6 signatures when the same package must also verify on older systems. Older RPM implementations may not understand RPMv6 signatures at all.

In practice, sign first with an OpenPGP v4-compatible algorithm (such as RSA) using --rpmv6. RPM can store both an RPMv6 signature and an RPMv4 compatibility signature for that classical key. Then add the PQC RPMv6 signature with a second rpmsign --addsign --rpmv6 pass.

After I signed first with the RSA key and then with the PQC key, verification showed both lines:

bash
rpmkeys -Kv ~/rpm-sign-lab/work/glc-hello-compat.rpm
output
/root/rpm-sign-lab/work/glc-hello-compat.rpm:
    Header V6 ML-DSA-87+Ed448/SHA512 Signature, key ID dea41aa1: OK
    Header V4 RSA/SHA512 Signature, key ID 8fe8b3a4: OK
    Header SHA256 digest: OK
    Header SHA1 digest: OK
    Payload SHA256 digest: OK
    MD5 digest: OK

Both lines must verify on RHEL 10.1+. The first compatible RSA RPMv6 signature can also be mirrored into the legacy RPMv4 signature slot, which is what older RPM versions use. An older system that only understands RPMv4 can still use that classical compatibility path when the signature is present.


Compatibility with RHEL 9 and older RPM versions

System RPMv4 RPMv6
RHEL 10.1+ Yes Native support in system rpm / rpmkeys
RHEL 10.0 Yes No native RPMv6 support like 10.1
RHEL 9.7+ Yes RPMv6 verification available through the documented multisig DNF plugin and pqrpm tooling, not as a drop-in replacement for classic rpmkeys alone
Older RHEL / older RPM RPMv4 is the compatibility path May ignore or lack RPMv6 support

Do not say “RHEL 9 cannot verify RPMv6.” Starting with RHEL 9.7, Red Hat documents RPMv6 verification via python3-dnf-plugin-multisig and the pqrpm helpers. That path uses a separate certificate database from the default RPM keyring. RHEL 10.1+ is still the release where system RPM verifies RPMv6 signatures natively without that plugin.


FIPS mode considerations

Keep this short: RHEL documents that sq cannot generate keys in FIPS mode because Sequoia still uses a deprecated OpenSSL API path for key generation (known issue on RHEL 10.1 and 10.2).

If your signing host must run FIPS, check the current RHEL known issues before you build the entire workflow around sq key generate on that host. Key generation outside FIPS (where policy allows) or another approved process may be required. This article’s lab host was not in FIPS mode (/proc/sys/crypto/fips_enabled was 0).

RHEL 10.1 also documents an rpm-sequoia issue with dual-signed packages when one of the signing algorithms is disabled by the active system-wide crypto policy. If a package with multiple otherwise-valid signatures fails verification, check current RHEL known issues and crypto-policy settings before assuming the RPM itself is corrupt.


Troubleshooting RPMv6 and Sequoia PGP

Problem Likely cause Fix
rpmsign does not recognize --rpmv6 RPM older than the RHEL 10.1 feature set Use RHEL 10.1+ (or a rebuild with the backport) and install rpm-sign
RPMv6 signature not shown Signed without --rpmv6, or only digests present Re-sign with rpmsign --addsign --rpmv6 and re-check with rpmkeys -Kv
Signature shows NOKEY Certificate not imported into the RPM keyring rpmkeys --import the matching OpenPGP certificate
One of several RPMv6 lines fails Missing trust for that signing key Import every certificate that produced a signature line
Dual-signed package fails verify despite valid signatures One signing algorithm disabled by crypto policy / known rpm-sequoia dual-sign issue Check RHEL known issues and system-wide crypto policy before assuming the RPM is corrupt
Older system cannot verify package No RPMv4-compatible signature present Sign with a classical algorithm first so an RPMv4 compatibility signature exists
PQC signing fails Wrong key profile, missing Sequoia macros, or crypto policy Confirm macros.rpmsign-sequoia, %_gpg_name fingerprint, and mldsa87 / rfc9580 key
sq key generation fails in FIPS mode Documented Sequoia / OpenSSL limitation See current RHEL known issues; generate keys outside FIPS if policy allows

Summary

RHEL 10 moved RPM OpenPGP verification to Sequoia PGP through rpm-sequoia. That change is already in place on RHEL 10.0 and does not require you to change how you run dnf install for signed distribution packages.

RHEL 10.1 adds native RPMv6 signature support on top of that backend. RPMv6 is a signature format that can carry multiple OpenPGP signatures on one package, including OpenPGP v6 and hybrid post-quantum signatures such as ML-DSA-87+Ed448. On this RHEL 10.2 lab, rpmsign --addsign --rpmv6 plus Sequoia keys produced verifiable multi-signature and PQC packages with rpmkeys -Kv.

When the same binary must still verify on older RPM stacks, keep an RPMv4-compatible classical signature in addition to any RPMv6 signatures. On RHEL 10.1+, if RPMv6 signatures are present they are what the system verifies, and every one of them must succeed. RHEL 9.7+ can verify RPMv6 signatures through the documented multisig / pqrpm path, which is not the same as native system RPM support on 10.1+.

For signing work, install sequoia-sq and rpm-sign, enable macros.rpmsign-sequoia, set %_gpg_name to a full fingerprint, and confirm results with rpmkeys -Kv after importing the certificates you actually signed with. Signing through those Sequoia macros remains a Technology Preview on RHEL 10.2.


References


Frequently Asked Questions

Does RHEL 10 use Sequoia PGP instead of GnuPG?

For verifying RPM package signatures, yes: RHEL 10 uses Sequoia through rpm-sequoia as the OpenPGP verification backend. That does not mean every tool on the system stopped using GnuPG. Signing with Sequoia via rpmsign and macros.rpmsign-sequoia is a separate, Technology Preview workflow. Many administrators still use GnuPG for other tasks.

What is an RPMv6 signature?

It is a newer RPM signature format that can hold multiple OpenPGP signatures on one package. On RHEL 10.1 and later, system RPM can verify those signatures natively. It is not the same statement as “this host runs RPM major version 6.”

Can one RPM have multiple signatures?

Yes, when you use RPMv6 signatures. Each rpmsign --addsign --rpmv6 with a different configured key can add another signature. All of those RPMv6 signatures must verify for the package to be trusted. On RHEL 10.1+, --addsign no longer removes existing signatures; use --resign when you want a clean replacement.

Does RHEL 9 verify RPMv6 signatures?

RHEL 9.7 and later can verify RPMv6 signatures using the documented multisig DNF plugin and pqrpm tooling. That is not identical to native verification in the default rpmkeys path on RHEL 10.1+. Older RHEL 9 releases without that support should rely on RPMv4-compatible signatures.

Does RPMv6 replace RPMv4 signatures?

No. RPMv4 signatures remain the compatibility path. RHEL 10.1 verifies RPMv6 signatures when they are present and otherwise falls back to RPMv4. Vendors that must support older verifiers should keep an RPMv4-compatible signature in addition to RPMv6 signatures.

What is a post-quantum RPM signature?

It is a package signature that uses algorithms designed to resist future quantum attacks, often in a hybrid form such as ML-DSA-87+Ed448. On RHEL 10.1+, you create those signatures with Sequoia (sq) and rpmsign --addsign --rpmv6, then verify them with rpmkeys -Kv after importing the certificate.

Do I need Sequoia PGP to install normal RPM packages?

No. End users installing signed RHEL packages with DNF do not need to run sq or change their install workflow. Sequoia already participates through rpm-sequoia during verification. You need sequoia-sq when you generate keys or sign packages yourself.

How do I check which signatures an RPM contains?

Run rpmkeys -Kv package.rpm (or rpm -Kv package.rpm). Each signature line reports the algorithm, a key ID or fingerprint, and OK / NOKEY / failure. Digest-only output means the file has no signature for RPM to check, or you are looking at an unsigned build.

Finished reading?Beta Get the key takeaways in seconds, then ask follow-up questions
Deepak Prasad

R&D Engineer

Founder of GoLinuxCloud with 15+ years of expertise in Linux, Python, Go, Laravel, DevOps, Kubernetes, Git, Shell scripting, OpenShift, AWS, Networking, and Security. With extensive experience, he excels across development, DevOps, networking, and security, delivering robust and efficient solutions for diverse projects.

  • Go (programming language)
  • Python (programming language)
  • DevOps
  • Computer Security
  • Cloud Computing
  • Kubernetes
  • Linux
  • Ansible (software)