GPG / PGP Signing
GPG / PGP Signing
Section titled “GPG / PGP Signing”Use QCecuring-managed GPG keys for signing Git commits, tags, RPM packages, DEB packages, and other artifacts — with private keys protected in HSM.
Architecture
Section titled “Architecture”┌──────────────┐ ┌──────────────────┐ ┌──────────────┐│ GPG CLI │──────►│ QCecuring Agent │──────►│ QCecuring ││ / git │ │ (PKCS#11 / │ │ Platform ││ │ │ gpg-agent) │ │ │└──────────────┘ └──────────────────┘ └──────────────┘ │ ▼ ┌──────────────┐ │ HSM │ │ (Private │ │ Keys) │ └──────────────┘Key points:
- GPG private keys are stored in the HSM, never exported
- Signing operations are proxied through the QCecuring Agent
- Integration via PKCS#11 token or custom gpg-agent socket
- Compatible with standard GPG workflows and tooling
Step 1: Generate or Import GPG Key in QCecuring
Section titled “Step 1: Generate or Import GPG Key in QCecuring”Generate a New GPG Key
Section titled “Generate a New GPG Key”- Navigate to Keys → Generate in the QCecuring platform
- Select key type: GPG / PGP
- Configure key parameters:
| Parameter | Recommended Value |
|---|---|
| Algorithm | RSA 4096 or Ed25519 |
| Usage | Sign, Certify |
| Expiration | 2 years |
| User ID | Your Name <email@example.com> |
| Subkeys | Signing subkey (recommended) |
- Click Generate — the key is created in the HSM
Import an Existing GPG Key
Section titled “Import an Existing GPG Key”# Export your existing private key (for import into QCecuring)gpg --export-secret-keys --armor KEY_ID > private-key.asc
# Import via QCecuring CLIqcecuring-agent gpg import \ --key-file private-key.asc \ --label "Developer Signing Key"
# Securely delete the exported key fileshred -u private-key.ascExport Public Key (for distribution)
Section titled “Export Public Key (for distribution)”# Export the public key from QCecuringqcecuring-agent gpg export-public \ --key-id "ABCD1234..." \ --output public-key.asc
# Import into local GPG keyring (public part only)gpg --import public-key.ascStep 2: Configure GPG to Use QCecuring
Section titled “Step 2: Configure GPG to Use QCecuring”Option A: PKCS#11 via gnupg-pkcs11-scd
Section titled “Option A: PKCS#11 via gnupg-pkcs11-scd”Install the PKCS#11 smart card daemon bridge:
# Install gnupg-pkcs11-scdsudo apt install gnupg-pkcs11-scd # Debian/Ubuntusudo yum install gnupg-pkcs11-scd # RHEL/CentOSConfigure ~/.gnupg/gnupg-pkcs11-scd.conf:
# QCecuring PKCS#11 providerproviders qcecuringprovider-qcecuring-library /usr/lib/qcecuring-pkcs11.solog-file /tmp/gnupg-pkcs11-scd.logConfigure ~/.gnupg/gpg-agent.conf:
scdaemon-program /usr/bin/gnupg-pkcs11-scdRestart the agent:
gpgconf --kill gpg-agentgpg --card-statusOption B: QCecuring gpg-agent Wrapper
Section titled “Option B: QCecuring gpg-agent Wrapper”Use the QCecuring agent as a drop-in gpg-agent replacement:
# Configure QCecuring as the GPG agentqcecuring-agent gpg configure \ --api-url https://platform.qcecuring.com \ --key-id "ABCD1234..."
# This creates/updates ~/.gnupg/gpg-agent.conf# and sets up the agent socketVerify the configuration:
# List available keys through the agentgpg --list-secret-keys
# Should show your QCecuring-managed key with a ">" indicator# sec> ed25519 2024-01-15 [SC] [expires: 2026-01-15]# ABCD1234EFGH5678...# uid [ultimate] Your Name <email@example.com># ssb> ed25519 2024-01-15 [S]Step 3: Sign Git Commits with Managed Keys
Section titled “Step 3: Sign Git Commits with Managed Keys”Configure Git for GPG Signing
Section titled “Configure Git for GPG Signing”# Set the signing keygit config --global user.signingkey ABCD1234EFGH5678
# Enable commit signing by defaultgit config --global commit.gpgsign true
# Enable tag signing by defaultgit config --global tag.gpgsign true
# (Optional) Set GPG program if using a custom pathgit config --global gpg.program gpgSign Commits
Section titled “Sign Commits”# Sign a commit (automatic if commit.gpgsign = true)git commit -S -m "feat: add new feature"
# Sign a taggit tag -s v1.0.0 -m "Release v1.0.0"
# Verify a signed commitgit log --show-signature -1
# Verify a signed taggit tag -v v1.0.0Upload Public Key to Git Hosting
Section titled “Upload Public Key to Git Hosting”# Export public key for GitHub/GitLabgpg --armor --export ABCD1234EFGH5678
# Add to:# GitHub: Settings → SSH and GPG keys → New GPG key# GitLab: Preferences → GPG KeysStep 4: Sign Packages with Managed Keys
Section titled “Step 4: Sign Packages with Managed Keys”RPM Package Signing
Section titled “RPM Package Signing”Configure RPM macros for GPG signing:
%_signature gpg%_gpg_name Your Name <email@example.com>%__gpg /usr/bin/gpgSign RPM packages:
# Sign a single RPMrpm --addsign mypackage-1.0-1.x86_64.rpm
# Sign multiple RPMsrpm --addsign *.rpm
# Verify RPM signaturerpm --checksig mypackage-1.0-1.x86_64.rpmImport the public key for verification on target systems:
# Export public key in RPM-compatible formatgpg --export --armor ABCD1234EFGH5678 > RPM-GPG-KEY-yourorg
# Import on target systemssudo rpm --import RPM-GPG-KEY-yourorgDEB Package Signing
Section titled “DEB Package Signing”Sign Debian packages with dpkg-sig:
# Sign a .deb packagedpkg-sig --sign builder mypackage_1.0-1_amd64.deb
# Verify signaturedpkg-sig --verify mypackage_1.0-1_amd64.debSign APT repository metadata with gpg:
# Sign Release file for APT repositorygpg --default-key ABCD1234EFGH5678 \ --armor --detach-sign \ --output Release.gpg Release
# Create InRelease (clearsigned)gpg --default-key ABCD1234EFGH5678 \ --clearsign \ --output InRelease ReleaseVerification Commands
Section titled “Verification Commands”Verify Git Signatures
Section titled “Verify Git Signatures”# Verify the latest commitgit verify-commit HEAD
# Verify a specific commitgit verify-commit abc1234
# Verify a taggit verify-tag v1.0.0
# Show signature in loggit log --show-signature --oneline -5Verify GPG Signatures (General)
Section titled “Verify GPG Signatures (General)”# Verify a detached signaturegpg --verify file.sig file
# Verify a clearsigned filegpg --verify signed-file.asc
# Check key detailsgpg --list-keys --keyid-format long ABCD1234EFGH5678Verify RPM Signatures
Section titled “Verify RPM Signatures”# Check RPM signaturerpm --checksig mypackage-1.0-1.x86_64.rpm
# Verbose verificationrpm -Kv mypackage-1.0-1.x86_64.rpmCI/CD Integration
Section titled “CI/CD Integration”GitHub Actions (Git Commit Signing)
Section titled “GitHub Actions (Git Commit Signing)”name: Signed Release
on: push: tags: ['v*']
jobs: release: runs-on: self-hosted # QCecuring Agent installed steps: - uses: actions/checkout@v4
- name: Configure GPG run: | qcecuring-agent gpg configure \ --key-id ${{ secrets.GPG_KEY_ID }}
- name: Build RPM run: ./build-rpm.sh
- name: Sign RPM run: rpm --addsign dist/*.rpm
- name: Verify Signatures run: rpm --checksig dist/*.rpm
- name: Upload Release uses: softprops/action-gh-release@v1 with: files: dist/*.rpmTroubleshooting
Section titled “Troubleshooting”| Issue | Cause | Resolution |
|---|---|---|
No secret key | GPG cannot reach QCecuring agent | Verify agent is running: qcecuring-agent status |
Unusable secret key | PKCS#11 module not loaded | Check gnupg-pkcs11-scd.conf path |
signing failed: No pinentry | Missing pinentry program | Install pinentry-curses or configure --batch mode |
| Git commit not showing as verified | Public key not uploaded to hosting | Add public key to GitHub/GitLab settings |
RPM --addsign hangs | Waiting for passphrase | Configure %__gpg_sign_cmd with --batch --pinentry-mode loopback |
card error from gpg | Agent socket misconfigured | Run gpgconf --kill gpg-agent and restart |
| Key not found after import | Key ID mismatch | Use gpg --list-keys to verify the correct key ID |
Best Practices
Section titled “Best Practices”- Use Ed25519 keys for new deployments (faster, smaller signatures)
- Set key expiration dates and rotate before expiry
- Use signing subkeys — keep the primary key for certification only
- Upload public keys to key servers and Git hosting platforms
- Enable
commit.gpgsign = trueglobally for all developers - Use separate keys for personal commits and CI/CD automation
- Audit signing operations in the QCecuring platform