GnuPG
This guide explains how Thales Luna HSM enhances the security of GnuPG by ensuring that private keys are created and stored inside secure hardware instead of the host system. GnuPG, the open-source implementation of Pretty Good Privacy (PGP), uses asymmetric cryptography where public keys are shared for encryption and private keys are required for decryption. Protecting the private key is essential because if it is compromised, the entire trust model is lost. By integrating with Luna HSM, all private key operations take place within a tamper-resistant environment controlled by enforced PINs, PED, and policies. Even if a workstation or account is compromised, the key cannot be extracted or misused. This approach provides strong access controls, prevents key export, meets compliance requirements, and significantly increases resistance to both physical and logical attacks.
The key benefits of this integration are:
- 
Secure generation, storage, and protection of the identity signing private keys using either FIPS 140-2 or FIPS 140-3 Level 3 validated hardware.
 - 
Full life cycle management of the keys to ensure their integrity and reliability throughout their usage.
 - 
Maintenance of a comprehensive HSM audit trail for transparency and accountability in key operations. It's important to note that Luna Cloud HSM service does not have access to this secure audit trail.
 - 
Significant performance enhancements by offloading cryptographic operations from application servers.
 
Supported Platforms
This integration has been validated with a range of enterprise Linux platforms to ensure secure operation with GnuPG. The table below lists the platform, GnuPG version, and PKCS#11 shim version that have been tested and approved.
Luna HSM
The following platforms have been certified for use with Luna HSM. Testing was performed in both HA and FIPS mode to ensure compliance and security across deployment scenarios.
| HSM Type | Platform Certified | GnuPG Version | PKCS11-SCD-Daemon | Notes | 
|---|---|---|---|---|
| Luna HSM | Red Hat Enterprise Linux 8.2 (64-bit) | 2.2.31 | 0.9.2 | Tested in HA and FIPS mode | 
| Luna HSM | Ubuntu 16.04 | 2.2.31 | 0.9.2 | Tested in HA and FIPS mode | 
| Luna HSM | Red Hat Enterprise Linux 7.7 (64-bit) | 2.0.22 | 0.9.1 | Tested in HA and FIPS mode | 
| Luna HSM | Red Hat Enterprise Linux 7.0 (64-bit) | 2.0.22 | 0.9.1 | Tested in HA and FIPS mode | 
| Luna HSM | Red Hat Enterprise Linux 6.5 (64-bit) | 2.0.14 | 0.9.1 | Tested in HA and FIPS mode | 
Luna Cloud HSM
The following platforms have been certified for use with Luna Cloud HSM. Testing was performed in both HA and FIPS mode to ensure compliance and security across deployment scenarios.
| HSM Type | Platform Certified | GnuPG Version | PKCS11-SCD-Daemon | 
|---|---|---|---|
| Luna Cloud HSM | Red Hat Enterprise Linux 8.2 (64-bit) | 2.2.31 | 0.9.2 | 
| Luna Cloud HSM | Red Hat Enterprise Linux 8.2 (64-bit) | 2.2.20 | 0.11.0 | 
| Luna Cloud HSM | Red Hat Enterprise Linux 7.7 (64-bit) | 2.0.22 | 0.9.1 | 
| Luna Cloud HSM | Red Hat Enterprise Linux 7.0 (64-bit) | 2.0.22 | 0.9.1 | 
Prerequisites
The prerequisites for this integration are:
Configure HSM Environment
As the first step to accomplish this integration, you need to configure either Luna HSM or Luna Cloud HSM.
Configure Luna HSM
Follow these steps to configure your Luna HSM:
Verify that the HSM is set up, initialized, provisioned, and ready for deployment.
Refer to Luna HSM documentation for detailed steps on creating NTLS connection, initializing the partitions, and assigning various user roles.
Create a partition on the HSM that will be later used by GnuPG. If you are using a Luna Network HSM, register a client for the system and assign the client to the partition to create an NTLS connection. Initialize the Crypto Officer and Crypto User roles for the registered partition.
Run the following command to verify that the partition has been successfully registered and configured:
/usr/safenet/lunaclient/bin/lunacm
You should see the following output:
lunacm (64-bit) v10.7.1-125. Copyright (c) 2024 Thales Group. All rights reserved. Available HSMs: Slot Id -> 0 Label -> TPA02 Serial Number -> 1280780175916 Model -> LunaSA 7.8.4 Firmware Version -> 7.8.4 Bootloader Version -> 1.1.5 Configuration -> Luna User Partition With SO (PW) Key Export With Cloning Mode Slot Description -> Net Token Slot FM HW Status -> Non-FM Current Slot Id: 0
Enable partition policies 22 and 23 to allow activation and auto-activation, in case you are using PED-authenticated HSMs.
Refer to Luna HSM documentation for detailed steps on creating NTLS connection, initializing the partitions, and assigning various user roles.
Manage User Access to Your HSM
Initially, only the root user can access the Hardware Security Module (HSM). However, you can grant access to specific non-root users by including them in the hsmusers group. This group is automatically created when you install the client software. Even if you later uninstall the client software, the hsmusers group remains intact, ensuring you can upgrade your software without losing your user access settings.
Add users to the hsmusers group
If you wish to permit non-root users or applications to interact with the HSM device, you must assign these users to the hsmusers group. Make sure that the users you intend to add to the hsmusers group are already established on the client workstation. Only users added to the hsmusers group will be granted access to the HSM device. Follow these steps to add a user to the hsmusers group:
Ensure that you possess sudo privileges on the client workstation.
Add a user to the hsmusers group using the command:
sudo gpasswd --add [username] hsmusers
Replace username with the actual username you want to include in the hsmusers group.
Remove users from the hsmusers group
If you need to withdraw a user's authorization to access the HSM device, you can remove them from the hsmusers group. Carry out the following steps to remove a user from the hsmusers group:
Confirm that you hold sudo privileges on the client workstation.
Eliminate a user from the hsmusers group using the command:
sudo gpasswd --add [username] hsmusers
Replace username with the specific username you want to exclude from the hsmusers group. To observe the changes, you will need to log in again.
Any user you remove will retain access to the HSM device until the client workstation is rebooted.
Set up Luna HSM High-Availability Group
Refer to Luna HSM documentation for HA steps and details regarding configuring and setting up two or more HSM boxes on host systems. You must enable the HAOnly setting in HA for failover to work so that if the primary goes down due to any reason, all calls get automatically routed to the secondary until the primary recovers and starts up.
Configure Luna Cloud HSM
Follow these steps to configure your Luna Cloud HSM:
Transfer the downloaded .zip file to your client workstation using pscp, scp, or other secure means
This integration has been certified on the RHEL platform.
Extract the .zip file into a directory on your client workstation.
Extract or untar the appropriate client package for your operating system. Do not extract to a new subdirectory; place the files in the client install directory.
tar -xvf cvclient-min.tar
Run the setenv script to create a new configuration file containing information required by the Luna Cloud HSM service.
source ./setenv
To add the configuration to an already installed UC client, use the –addcloudhsm option when running the setenv script.
Run the LunaCM utility and verify the Cloud HSM service is listed.
If your organization requires non-FIPS algorithms for your operations, ensure that the Allow non-FIPS approved algorithms check box is checked. For more information, refer to Supported Mechanisms.
Install GPG-Dependent Packages
Before beginning the integration, install the following GPG-dependent packages from the official GnuPG source:
- 
npth
 - 
libgpg-error
 - 
libgcrypt
 - 
libksba
 - 
libassuan
 
Install Pinentry Package
To enable partition access authentication for GPG, you can use the salogin utility included with the Thales Luna Client software. If you prefer not to use salogin, install the Pinentry package (such as pinentry-curses or pinentry-tty) from the official GnuPG source.  
Install GnuPG Package
After successfully building and installing the prerequisite libraries listed above, proceed with installing the GnuPG package (version 2.2 or later) from the official GnuPG source.
Install gnupg-pkcs11-scd and pkcs11-helper
Once GnuPG is installed, install the pkcs11-helper and gnupg-pkcs11-scd components along with their libraries. Ensure the correct version of these libraries is used at runtime by setting the library path:
export LD_LIBRARY_PATH=/usr/local/lib
Integrating GnuPG with Luna HSM
This procedure describes how to integrate GnuPG with a Luna HSM for secure key management and cryptographic operations. The following sub-procedures are included:
Configure gnupg-pkcs11-scd.conf
Generate Keys and Certificates
Configure GnuPG to Use PKCS#11 Smart Card Daemon
Access Luna HSM
You can access Luna HSM for GPG using either of the following methods:
Using salogin Utility
The salogin utility allows you to establish a persistent session, so you do not need to enter the password each time GPG accesses the HSM object. To configure a persistent session:
Persistent sessions are not supported for Luna Cloud HSM. For Luna Cloud HSM, refer to the Using Pinentry section below.
Add the following text to the /etc/Chrystoki.conf file:
Misc = {
AppIdMajor=1;
AppIdMinor=1;
}
Run the following command to open the authenticated persistent session for accessing the HSM object:
./salogin -o -s 0 -i 1:1 -p
In this command, -s specifies the slot ID, and -i specifies the AppId defined in the Chrystoki.conf file.
Using Pinentry
Pinentry is an alternative method for authenticating partition access in GPG. To configure Pinentry authentication:
Create the .gnupg directory in your home folder if it does not already exist.
Create the gpg-agent.conf file inside the .gnupg directory if it does not already exist.
Open the gpg-agent.conf file in a text editor.
Add the following line to specify the Pinentry program to be used:
pinentry-program /usr/local/bin/pinentry
Configure gnupg-pkcs11-scd.conf
This step is required only when using Pinentry with GPG v2.0.x or earlier. Skip this step if you are using GPG v2.2.x.
To configure the gnupg-pkcs11-scd.conf file:
Locate the configuration file in the ~/.gnupg/ directory. If the file does not exist, copy the example file from either /usr/local/etc/gnupg-pkcs11-scd.conf.example or /usr/local/share/doc/gnupg-pkcs11-scd/gnupg-pkcs11-scd.conf.example and rename it as gnupg-pkcs11-scd.conf.
Open ~/.gnupg/gnupg-pkcs11-scd.conf in a text editor.
Add, modify, or uncomment the following lines:
provider-p1-allow-protected-auth provider-p1-cert-private provider-p1-private-mask 0
Generate Keys and Certificates
To generate an RSA key pair on the Luna HSM for use with GnuPG, perform the following steps:
Generate a 32-byte hexadecimal value to be used as the Key ID. You can use either of the following Linux commands:
head -c16 </dev/urandom | xxd -p -u
or
xxd -len 16 -plain /dev/urandom
Use the generated hexadecimal value as the Key ID for your GPG key. GPG uses this Key ID to retrieve the key from the Luna HSM, so ensure the same Key ID is assigned to both the key pair and the certificate.
Open the CMU utility provided with the Luna Client. The CMU utility is located in the /usr/safenet/lunaclient/bin directory. Run the following command to generate RSA 2048-bit key pairs:
/usr/safenet/lunaclient/bin/cmu generatekeypair -modulusBits=2048 -publicExponent=65537 -labelPublic=GPG-Sign-Pub -labelPrivate=GPG-Sign-Priv -sign=1 -verify=1 -encrypt=1 -decrypt=1 -wrap=1 -unwrap=1 -id=c50f7b86372b441ba77cb6f8598f1e35
When prompted, enter the partition password and select the appropriate RSA Mechanism Type. For example, select PKCS by entering 1 when prompted.
Command-line parameters for the CMU utility may vary depending on the Luna Client version. Refer to the official Luna HSM documentation for details on supported options.
View the objects created on the HSM partition to verify key generation. Run the following command and make a note of the handle values assigned to the public and private keys:
/usr/safenet/lunaclient/bin/cmu list
When prompted, enter the partition password. Example output:
handle=34 label=GPG-Sign-Pub handle=35 label=GPG-Sign-Priv
Generate a self-signed certificate using the previously created key pair.
Run the following command and provide the required certificate attributes when prompted:
/usr/safenet/lunaclient/bin/cmu selfsigncertificate -label=GPG-Sign -publichandle=34 -privatehandle=35 -startDate=20210925 -endDate=20220925 -serialNumber=0133337A -keyusage=digitalsignature,keyencipherment -id=c50f7b86372b441ba77cb6f8598f1e35 Please enter password for token in slot 0 : ******** Enter Subject 2-letter Country Code (C) : IN Enter Subject State or Province Name (S) : UPST Enter Subject Locality Name (L) : NOIDA Enter Subject Organization Name (O) : THALES Enter Subject Organization Unit Name (OU) : HSM Integration Enter Subject Common Name (CN) : GPG-Signing Enter EMAIL Address (E) :
For Luna Cloud HSM, replace publichandle and privatehandle with publicouid and privateouid, respectively.
During certificate generation, you will be prompted to enter attributes such as Country (C), State (S), Locality (L), Organization (O), Organizational Unit (OU), Common Name (CN), and Email (E).
Ensure that the id value remains the same for both the keys and the certificate. GPG relies on this consistency to reference the correct key objects.
If your organization does not allow self-signed certificates, generate a certificate request and have it signed by a trusted Certificate Authority.
After receiving the CA-signed certificate, import both the CA and signed certificate into the Luna HSM:
./cmu import -inputFile CA-signed-cert.crt -label GPG-Cert -private F
After importing, set the ID attribute to match the existing key pair:
./cmu setattribute -handle 53 -id c50f7b86372b441ba77cb6f8598f1e35
If you require different keys and certificates for encryption or authentication, repeat all key and certificate generation steps using unique id and label values.
Configure GnuPG to Use PKCS#11 Smart Card Daemon
To enable the gpg-agent to use the PKCS#11 smart card daemon for accessing keys on the Luna HSM, complete the following steps:  
Open (or create, if it does not exist) the ~/.gnupg/gpg-agent.conf file and add the following line to specify the smart card daemon program:
scdaemon-program /usr/local/bin/gnupg-pkcs11-scd
Open the ~/.gnupg/gnupg-pkcs11-scd.conf file and ensure the following configuration is present:
providers p1 provider-p1-library /usr/safenet/lunaclient/lib/libCryptoki2_64.so
If the gnupg-pkcs11-scd.conf file does not exist, copy the example configuration file from either /usr/local/etc/gnupg-pkcs11-scd.conf.example or /usr/local/share/doc/gnupg-pkcs11-scd/gnupg-pkcs11-scd.conf.example, and rename it to gnupg-pkcs11-scd.conf in the ~/.gnupg directory.
Ensure that the library path specified under provider-p1-library is correct, especially when using Luna Cloud HSM.
Set the following environment variables to ensure the correct GnuPG version and libraries are used at runtime:
export LD_LIBRARY_PATH=/usr/local/lib:$LD_LIBRARY_PATH export PATH=/usr/local/bin:$PATH
For GPG v2.2.x
Use the following procedure to configure and verify GPG integration with Luna HSM when using GPG version 2.2.x:
Run the following command to allow GPG to discover available information from the connected card or HSM partition:
gpg --card-status
Run the following command to connect the GPG agent to the HSM and retrieve key information:
gpg-agent --server gpg-connect-agent
At the gpg-connect-agent prompt, enter the command SCD LEARN. The Pinentry program prompts for the partition password; after successful authentication, the output displays information retrieved from the HSM. Locate the line that begins with S KEY-FRIENDLY and note the 20-byte hash value. This value serves as the keygrip, which will be required in later steps.

Generate the GPG virtual keys using the command gpg --expert --full-generate-key and follow the on-screen prompts to select the key type and purpose, provide your real name (used for RPM signing), enter the associated email address, and specify the key validity period. The keys are not created locally; GPG only generates references to the keys stored in the HSM.

After the virtual keys have been generated, verify them by listing the keys:
gpg --list-keys

For GPG v2.0.x
Use the following procedure to configure and verify GPG integration with Luna HSM when using GPG version 2.0.x:
Connect the GPG agent to the HSM and retrieve key information by running:
gpg-agent --server gpg-connect-agent
At the gpg-connect-agent prompt, enter SCD LEARN. The Pinentry program prompts for the partition password; however, if a persistent session was previously opened using the salogin utility, the password prompt will not appear. Review the command output to identify the signing, encryption, or authentication certificate, locate the line beginning with S KEY-FRIENDLY, and copy the associated 20-byte SHA-1 hash.

Add the hashes to the ~/.gnupg/gnupg-pkcs11-scd.conf file as follows:
openpgp-sign 8C5CE31F726FE84CBB0891E0E2816F2EF07F0000 openpgp-encr 7990A0D320B59A0DA525CE39D15398743762EFBB openpgp-auth 8B91705A7B3ED221AAFF5E78B95C89DD4EB0DDCD
The 20-byte hash values will be the same if the same key is used for all functions.
Enable GPG to discover the card or HSM partition details by executing the following command:
gpg --card-status

Generate the GPG virtual keys by executing the following sequence of commands: gpg --card-edit, admin, and generate. When prompted, respond y to replace existing keys, choose not to back up the keys, set the key expiry parameters, and enter the real name, which will serve as the reference for RPM signing going forward.
Test GnuPG Integration with Luna HSM
You can test GPG functionality with Luna HSM in the following use cases:
File Signing and Verification
To sign and verify a file using the keys stored in the Luna HSM, perform the following steps:
Sign the file by running the following command. Replace <Your key name> with the real name of the key and somefile with the actual file name:
gpg --sign --default-key <Your key name> somefile
Authenticate by entering the partition password when prompted. If a persistent session was opened using the salogin utility, no password prompt will appear. After signing, a new file named somefile.gpg is created, containing the original content and its digital signature.
Verify the signed file using the following command. The contents of the verified file should match the original file, confirming successful signing and verification.  
gpg somefile.gpg
RPM Signing and Verification
RPM signing uses GnuPG for key management and cryptographic operations to ensure the authenticity and integrity of software packages. The following procedures describe how to set up the environment, sign RPMs, and verify signed packages using keys stored on the Luna HSM.
Set Up the Environment
Before signing or verifying RPM packages, set up the environment as described below.
Run the following commands to initialize the terminal for GPG operations:
GPG_TTY=$(tty) export GPG_TTY
This step is required only for GPG v2.0.x. Skip it if you are using GPG v2.2.x.
Create or update the ~/.rpmmacros file to define how RPM interacts with GPG. The file should include the following configuration:
%_signature gpg
%_gpg_path /root/.gnupg
%_gpg_name GPG-Sign
%__gpg /usr/local/bin/gpg
%__gpg_sign_cmd %{__gpg} gpg --force-v3-sigs --batch --verbose --no-armor --no-secmem-warning -u "%{_gpg_name}" -sbo %{__signature_filename} --digest-algo sha256 %{__plaintext_filename}'
Where:
- 
_signature must be set to
gpg - 
_gpg_path specifies the path to the
.gnupgdirectory - 
_gpg_name must match the user name (Real Name) of the key
 - 
__gpg defines the full path to the GPG binary
 - 
__gpg_sign_cmd specifies the signing command and enforces SHA-256 as the digest algorithm
 
Sign an RPM
You can sign an RPM package using either the standard RPM command or an automated script.
Using the RPM Command
Sign an RPM file by running the following command, replacing example.rpm with the actual RPM file name:
rpm --addsign example.rpm
If you need to re-sign an existing RPM, use the following command:
rpm --resign example.rpm
Using an Automated Script
Ensure that the expect package is installed. If not, install it using:
yum install expect
Create an expect script using the following template, updating the key name as needed:
#!/usr/bin/expect --
spawn rpm --define "_gpg_name  GPG-Sign" --resign {*}$argv
expect {
  "Enter pass phrase:" { send "\r" ; exp_continue }
  eof
}
Save the script, make it executable, and use it to sign RPM files by running:
./<scriptname> <your_rpm>
Replace <scriptname> with the name of your script file and <your_rpm> with the actual RPM file name. 
The Pinentry program may prompt for the partition password during RPM signing. If a persistent session has been opened using salogin, or if the PIN is already cached, you will not be prompted. Each RPM signing operation involves three internal signing actions, so you may be prompted multiple times if no persistent session exists.
Verify a Signed RPM
To verify the digital signature of an RPM package, follow the steps below:
Export the public key associated with the signing key:
gpg --export --armor <your_keyname> > <your_keyfile>
Example:
gpg --export --armor GPG-Sign > gpg.key
Import the exported public key into the local RPM keychain:
rpm --import <your_keyfile>
Example:
rpm --import gpg.key
Verify the signature on the RPM file using the following command:
rpm --checksig <your_rpm>
Example:
rpm --checksig example.rpm
If the signature is valid, you will see an output similar to the following:
example.rpm: rsa sha1 (md5) pgp md5 OK
The RPM verification output may appear generic because SHA1 and MD5 digests are part of the package metadata. To view the exact signing algorithm and related signature details, run the command rpm -q --qf '%{SIGPGP:pgpsig} %{SIGGPG:pgpsig}\n' -p example.rpm. The output will display the algorithm, timestamp, and key ID used for signing, for example: RSA/SHA256, Thursday 30 September 2021 01:50:59 AM IST, Key ID ad05dbb378832d9b (none).
Perform Unattended RPM Signing
In automated build environments, RPMs are often generated in bulk, making manual password entry impractical. You can automate the signing process by configuring GPG Agent and using an Expect script to handle passphrase prompts.
Start the GPG agent daemon to cache the partition password for future signing operations:
gpg-agent --daemon
The gpg-agent process runs in the background and retains the cached partition password for the session. For details on available options and configuration parameters, refer to the official GnuPG gpg-agent documentation.
Create an Expect script to automate RPM signing.
Create a file named rpm-sign.exp and add the following content:
#!/usr/bin/expect --
spawn rpm --define "_gpg_name <your keyname here>" --resign {*}$argv
expect {
  "Enter pass phrase:" { send "\r" ; exp_continue }
  eof
}
Expect automates text-based interactions with terminal applications. To install Expect on RHEL or CentOS systems, use yum install expect expectk.
Use the created script to sign RPM packages automatically:
./rpm-sign.exp <rpm_name>
Replace <rpm_name> with the name of the RPM file you want to sign.