Skip to content

47-Day Certificates Are Coming. Are You Ready?

Act Now →

How to sign RPM packages?

Signing RPM Packages

RPM (Red Hat Package Manager) is a package management system used in Linux distributions, particularly those based on Red Hat, such as Fedora and CentOS. RPM packages are software bundles that contain executable files, libraries, documentation, and other resources required for a specific application or service to function correctly on a Linux system.

RPM packages are compressed archives that follow a specific file format and naming convention. They typically have the extension “.rpm” and can be installed, upgraded, or removed using RPM package management tools.

The RPM package format is widely used in many Linux distributions, and it simplifies software management by providing a standardized and reliable method for packaging and distributing software.

Signing an RPM package, in short: generate an HSM-backed GPG key pair, import it into your GPG keyring via a PKCS#11 bridge, then run the RPM Signer utility with your key name, fingerprint, and issuer email. The tool produces a detached signature file, a separate artifact linked to the package, distinct from the traditional rpm --addsign model that embeds the signature directly in the RPM header.

Key Takeaways

  • This tool produces a detached .sig file rather than embedding the signature in the RPM header. That means standard RPM tooling (rpm -K, rpm --checksig) won’t verify it directly; verification must go through the RPM Signer utility’s own verify subcommand instead.
  • The key fingerprint (-f) must be the exact hex fingerprint of the GPG key generated on the HSM, not a key name or email; a mismatch here is a common source of signing failures.

Environment Matrix

ComponentRequirement
OSLinux (Debian/Ubuntu shown; RPM-based distributions like Fedora/CentOS are the typical target for the packages themselves)
HSM integrationPKCS#11-compatible HSM (nCipher/nfast shown) bridged to GPG via gnupg-pkcs11-scd
Python dependenciescrypto==1.4.1, cryptography==40.0.2, pycryptodome==3.16.0, requests==2.28.2
Client authenticationSSL Client Authentication Certificate in PKCS12 format (.p12 or .pfx)
Supported hash algorithmsSHA224, SHA256 (default), SHA384, SHA512
Signature formatDetached signature file, not embedded in the RPM header

Overview

To sign RPM packages with GPG keys, the following steps are typically involved:

  1. Generate GPG Key Pair

    The package maintainer or distributor generates a GPG key pair consisting of a private key and a corresponding public key. The private key is kept secure (preferably in HSM) and should not be shared, while the public key can be distributed widely.

  2. Configure RPM Signing

    The GPG public key is added to the RPM package manager’s keyring, allowing it to verify the packages signed with the corresponding private key. This step ensures that the package manager recognizes the GPG key as trusted.

  3. Sign RPM Packages

    The package maintainer signs the RPM packages using the private key associated with the GPG key pair. This process generates a digital signature for each package.

  4. Verify RPM Packages

    When the RPM package manager encounters a signed package, it uses the GPG public key to verify the package’s signature. It checks whether the signature is valid and matches the package’s content, ensuring that it hasn’t been modified or tampered with since it was signed.

RPM signing with GPG keys adds additional security to RPM packages. It helps to establish the authenticity and integrity of the packages by confirming that they were signed by the entity possessing the private key associated with the GPG public key. This method allows users and systems to verify the trustworthiness of RPM packages before installation and guards against unauthorized modifications or malicious tampering.

Prerequisites

  1. Generate key pair on HSM

    1. Change directory to /opt/nfast/bin

      $ cd /opt/nfast/bin

    2. Execute the command and enter the appropriate details

      $ ./generatekey pkcs11 selfcert=yes

      Note: Remember your key’s name and email address, as they will be required in the subsequent steps.

    3. Execute command

      $ ./ckcerttool -n -f pkcs11_ua4335d6933d9809f048dcf4bc47c90194f2f7ba4b_selfcert -k ua4335d6933d9809f048dcf4bc47c90194f2f7ba4b -L rpmtest

      Here, the “-f” option corresponds to “self-cert,” the “-k” option refers to the key, and the “-L” parameter should match the Key name entered previously.

    4. Install the gnupg-pkcs11-scd

      $ sudo apt-get install gnupg-pkcs11-scd

      Note: If you encounter any issues with executing the “sudo apt-get install” command, try running the following command beforehand.

      $ sudo apt-get update && sudo apt-get upgrade -y

    5. Configure gnupg agent

      • Edit the following lines in the gpg-agent.conf

        $ nano ~/.gnupg/gpg-agent.conf
        - Enter the below lines and save the file
        scdaemon-program /usr/bin/gnupg-pkcs11-scd
        pinentry-program /usr/bin/pinentry

      • Edit the following lines in the gnupg-pkcs11-scd.conf

        $ nano ~/.gnupg/gnupg-pkcs11-scd.conf
        - Enter the below lines and save the file
        providers p1
        provider-p1-library /opt/nfast/toolkits/pkcs11/libcknfast.so

    6. Reload the agent

      $ gpg-agent --server gpg-connect-agent <<EOF
      > RELOADAGENT
      > EOF

    7. Get the GPG KEY-FRIENDLY string (of the newly generated key)
      • Retrieve card details

        $ gpg --card-status

      • Retrieve key-friendly names and certificates

        $ gpg-agent --server gpg-connect-agent << EOF
        > SCD LEARN
        > EOF

    8. Import the key into GPG 2 keyring

      $gpg --expert --full-generate-key

      Note: Enter key-friendly generated previously under the “Enter the keygrip” parameter.

    9. To check the key in the gpg key ring, execute the below command.

      $ gpg --list-keys

  2. Set environment variables for the SSL Client Authentication Certificate path and certificate password.

    Note: SSL Client Authentication Certificate should be in the PKCS12 format (.p12 or .pfx)

    Execute the bellow command to set environment variables:

    • Mac or Linux

      $ export EC_Client_Auth=path_to_ssl_certificate
      $ export EC_Client_Pass=your_client_certificate_password

    • Windows

      $ set EC_Client_Auth=path_to_ssl_certificate
      $ set EC_Client_Pass=your_client_certificate_password

  3. Install all the following requirements:

    • crypto==1.4.1
    • cryptography==40.0.2
    • pycryptodome==3.16.0
    • requests==2.28.2

Enterprise Code-Signing Solution

Get One solution for all your software code-signing cryptographic needs with our code-signing solution.

How to use the RPM Signer utility?

Get the version of the RPM Signer Utility

Execute the below command

$ python3 rpmsigner.py -v or $ python3 rpmsigner.py --version

Sign an RPM package

Execute the below sign subcommand to sign an RPM package.

Syntax:

python3 rpmsigner.py sign <file_to_be_signed> -u <user_name> -k <key_name> -i <issuer_email> -f <key_fingerprint> -a <algorithm> [-o <output_sig_file_name>]

Parameters:

  • sign: RPM Package to be signed.
  • -u: A username on Encryption Consulting Code Signing Server.
  • -k: Key/certificate name for signing/verification provided by Encryption Consulting Code Signing server.
  • -i: User email address used to generate key pair.
  • -f: gpg key fingerprint in hex format.
  • -a: Algorithm to be used for signing. One of the below options to be used:
    • SHA224
    • SHA256 (Default)
    • SHA384
    • SHA512

    If the algorithm is not provided, it will use SHA256 as a default.

  • -o: Output file to store signature. This is an optional parameter. If this option is provided, a signature file will be generated as per the given name <file_to_be_signed>.sig
  • -h: Display help.
  • -v: Display verbose logs.

Example:

python3 rpmsigner.py sign test_rpm_signer.rpm -u admin -k RPMtestcert -i [email protected] -f 3E633D3878815FAC111CF488FC15CA0088C43155 -a SHA256 -o myFile.sig

Verify an RPM package

Execute the below verify subcommand to verify the signature of an RPM package.

Syntax:

python3 rpmsigner.py verify <file_to_be_verified> -u <user_name> -k <key_name> -i <issuer_email> -f <key_fingerprint> -a <algorithm>

Example:

python3 rpmsigner.py verify test_rpm_signer.rpm -u admin -k RPMtestcert -i [email protected] -f 3E633D3878815FAC111CF488FC15CA0088C43155 -a SHA256

A successful verification returns a confirmation that the signature matches the package content and the specified key; a mismatch or tampering returns a failure indicating the package should not be trusted. Since this is a detached signature rather than an embedded RPM header signature, always verify through this utility rather than assuming rpm -K will report anything about it.

Common Errors

ErrorLikely CauseFix
Key not found / fingerprint mismatchThe -f value doesn’t exactly match the hex fingerprint of the HSM-backed GPG keyRe-run gpg --list-keys to confirm the exact fingerprint rather than reusing a value from memory or an old command
Authentication failure connecting to signing serverEC_Client_Auth or EC_Client_Pass environment variables not set or incorrectRe-verify both are exported in the current shell session, not just set in an unsourced script
gpg-agent fails to find the scdaemongpg-agent.conf or gnupg-pkcs11-scd.conf paths are misconfigured, or the agent wasn’t reloaded after editingConfirm the scdaemon-program path is correct and re-run the RELOADAGENT command after any config change

CI/CD Use and Cleanup

For repeated signing in a pipeline, set EC_Client_Auth and EC_Client_Pass as pipeline secrets rather than hardcoding them, and pin the exact key fingerprint as a pipeline variable rather than looking it up interactively each run. Verify idempotency by running the verify subcommand immediately after signing and failing the build on anything other than a successful match, rather than trusting the sign command’s exit code alone.

For cleanup: if the .p12/.pfx client authentication certificate was copied to a build agent for testing, remove it once the pipeline is confirmed working, and prefer injecting it as a pipeline secret at runtime instead.

Want to know how we can assist you?

Enterprise Code-Signing Solution

Get One solution for all your software code-signing cryptographic needs with our code-signing solution.

Encryption Consulting’s CodeSign Secure provides organizations with a comprehensive code-signing solution tailored to their unique requirements. By utilizing this solution, organizations can establish a strong code-signing policy that effectively mitigates security risks and ensures the authenticity of their software. Our product streamlines the code-signing process and offers a range of features designed to enhance security.

One key feature of CodeSign Secure is secure key management. It enables organizations to securely store their private keys of the code-signing certificate by integrating with industry-leading Hardware Security Modules (HSMs) that are FIPS certified. This integration eliminates the potential risks associated with stolen, corrupted, or misused keys, as the private keys never leave the HSM during the code signing operation.

Frequently Asked Questions

Will `rpm -K` or `rpm –checksig` verify a package signed with this tool?

No. This tool produces a detached signature file rather than embedding the signature in the RPM header, which is what standard RPM tooling checks. Verify using the RPM Signer utility’s own verify subcommand instead.

What exactly goes in the -f (fingerprint) parameter?

The full hex fingerprint of the GPG key generated on the HSM, obtained via gpg --list-keys, not the key name or email address used for the other parameters.