Home / Alt manpages / gpgsm(1)

  • gpgsm(1)
  • User command
  • linux

Use gpgsm for Practical CMS Signing and Encryption

You will finish with a repeatable workflow for inspecting X.509 certificates and using gpgsm to create or verify CMS signatures and encrypt or decrypt CMS data. The examples target the installed GnuPG 2.4.4, from package version 2.4.4-2ubuntu17.6. They use placeholder paths and certificate identities, so replace those values with identities you have checked.

Allow 20 minutes for a first run, plus time to obtain a suitable certificate and private key. You need a shell, the gpgsm package, and an X.509 certificate in PEM or binary form. Signing and decryption also require the matching private key, normally managed through gpg-agent. No example needs root privileges.

1. Confirm the installed tool

Start by checking the version and the available certificate database. This reads your normal GnuPG home, usually ~/.gnupg, but changes nothing:

$ gpgsm --version
gpgsm (GnuPG) 2.4.4

$ gpgsm --list-keys

The second command may print no certificates and still exit successfully. It creates the local keybox on first use if one does not exist. A normal listing is formatted for people; use --with-colons when another program must parse the records.

Checkpoint

Record the exact certificate identity or fingerprint you intend to use. Do not rely on a short name when more than one certificate could match.

2. Inspect a certificate before importing it

Inspect a certificate file without adding it to the keybox:

$ gpgsm --show-certs /path/to/recipient.crt

The input may be a single binary certificate or one or more PEM certificates. Review the subject, issuer, validity dates and fingerprint. PEM input normally starts with -----BEGIN CERTIFICATE-----. If automatic input detection fails, try --assume-armor for PEM or --assume-binary for binary input.

Import only a certificate whose source and fingerprint you trust:

$ gpgsm --import /path/to/recipient.crt
gpgsm: total number processed: 1
gpgsm:               imported: 1

Output varies when the certificate is already present, so verify the result by listing the database:

$ gpgsm --list-keys --with-colons

For a certificate that must pass chain validation before import, add --with-validation. That can contact certificate-revocation services through Dirmngr and can be slow. Treat a validation failure as a reason to investigate the certificate, not as a prompt to disable checks.

3. Create a signed CMS message

Use a clear output path and select the signing certificate explicitly. The installed program writes binary output by default; --armor makes PEM-encoded CMS output that is easier to move through text-based systems.

$ gpgsm --sign --local-user 'SIGNER_ID_OR_FINGERPRINT' \
    --armor --output signed-message.pem /path/to/message.txt
$ head -n 1 signed-message.pem
-----BEGIN CMS-----

The local user value may be a fingerprint, exact email address, subject DN or another supported user-ID pattern. A fingerprint is the least ambiguous choice. Without --local-user, gpgsm uses the first secret key it finds, which is a poor default for unattended jobs.

For a detached signature, use the command shown by the installed help:

$ gpgsm --detach-sign --local-user 'SIGNER_ID_OR_FINGERPRINT' \
    --armor --output message.sig /path/to/message.txt

Keep the original message beside the detached signature. The signature does not contain a replacement copy of the message.

4. Verify the signature

Verify an attached CMS message with:

$ gpgsm --verify signed-message.pem

For a detached signature, provide the signature and then the original data:

$ gpgsm --verify message.sig /path/to/message.txt

A successful exit status means the cryptographic check completed. It does not by itself prove that you trust the issuing certificate or that the message came from the person you expected. Review gpgsm's diagnostic output and certificate chain for that decision.

Checkpoint

Immediately capture the status when scripting a verification:

if gpgsm --verify message.sig /path/to/message.txt; then
    printf '%s\n' 'signature check passed'
else
    status=$?
    printf 'signature check failed, status %s\n' "$status" >&2
    exit "$status"
fi

5. Encrypt for a recipient and decrypt locally

First confirm that the recipient certificate is in your keybox, then encrypt to an identity that you have matched to the inspected certificate:

$ gpgsm --encrypt --recipient 'RECIPIENT_FINGERPRINT' \
    --armor --output encrypted-message.pem /path/to/message.txt
$ head -n 1 encrypted-message.pem
-----BEGIN CMS-----

Encryption can use more than one --recipient, so each intended recipient can decrypt a copy of the content. The sender does not automatically gain a decryptable copy. Add your own certificate as another recipient if you need to decrypt the result later.

Decrypt with the matching private key available to gpg-agent:

$ gpgsm --decrypt --output recovered-message.txt encrypted-message.pem
$ cmp -- /path/to/message.txt recovered-message.txt

A successful cmp prints nothing and returns status 0. Decryption may open Pinentry for the private-key passphrase. Do not put a passphrase in a command line or a shell history. For automation, study --batch, --pinentry-mode and the agent configuration together; casually adding --batch can turn an interactive request into a failure.

6. Keep certificate checks and output predictable

Certificate-revocation-list checks are enabled by default and use Dirmngr. Leave that behaviour in place for normal signing and verification. The manual documents --disable-crl-checks mainly for offline operation, but it weakens certificate checking and also changes issuer-certificate retrieval. Use it only for a stated, controlled offline requirement, and do not bake it into a general configuration file.

Use --status-fd when a program needs machine-readable operation status, rather than scraping human diagnostics. Keep status output separate from the CMS data, especially when writing the data to standard output. Similarly, use --output for files and check that a previous file will not be overwritten before running a command.

Configuration comes from gpgsm.conf under the GnuPG home unless --options selects another file. For a test or a service account, isolate state with an explicit home directory. Do not copy a private key into a shared temporary directory, and do not use --homedir as a way to bypass ownership or trust checks.

7. Recover from common failures

  • If gpgsm says no suitable certificate was found, run gpgsm --list-keys --with-colons and compare the full fingerprint with the recipient or signer value.
  • If signing or decryption asks for a key that is absent, the certificate may be present without its private key. Check with gpgsm --list-secret-keys; importing a public certificate alone cannot create the secret part.
  • If verification fails after the file was transferred through a text system, compare hashes of the original and received files. Do not edit a CMS file or convert line endings.
  • If certificate validation cannot reach its revocation service, fix Dirmngr connectivity or use an explicitly isolated offline process. Do not treat --disable-crl-checks as a universal repair.

Warning

gpgsm --delete-keys PATTERN removes matching certificates from the local keybox. It does not provide a command to delete a secret key directly, and key deletion can make later operations harder to recover. Export or back up what you need first, and never use a broad pattern in a cleanup script.

Done means

  • The installed version is known and the intended certificate was inspected by fingerprint.
  • Recipient certificates are imported and visible in gpgsm --list-keys.
  • A CMS signature verifies, with the exit status checked rather than just the screen text.
  • Encryption and decryption produce matching files without exposing a passphrase.
  • Default revocation checks remain enabled unless a documented offline exception is genuinely required.