How to Sign security.txt with PGP

A PGP cleartext signature proves your security.txt really comes from you — without it, anyone who compromises your web server can silently redirect vulnerability reports to themselves. This guide walks through generating a key with GnuPG, publishing it, and signing the file.


RFC 9116 recommends signing security.txt with an OpenPGP cleartext signature. The reason is subtle but important: the file's whole job is to tell researchers where to send vulnerability reports — so an attacker who compromises your web server could swap in their own contact address and quietly intercept every report. A signature made with a key you control lets researchers detect that tampering. This guide covers generating the key with GnuPG, publishing it, and signing the file.

Generate the Key Locally — Never in a BrowserThis key is your organisation's security-contact identity. Generate it on a trusted machine with gpg (or on a hardware token such as a YubiKey) and keep the private key offline. Never generate or paste a signing key into a website — including this one. That is why ShowDNS provides this guide rather than a "PGP key generator" tool.

Step 1 — Generate a PGP Key with GnuPG

GnuPG ships with most Linux distributions and macOS (via brew install gnupg); Windows users can install Gpg4win. Create a modern Ed25519 key bound to your security role address — not a personal mailbox:

bash
gpg --quick-generate-key "Example Corp Security <security@example.com>" ed25519 sign 2y

You will be prompted for a passphrase — use a strong one and store it in your team's password manager. The 2y expiry is deliberate: like the Expires field in security.txt itself, a key that must be renewed periodically proves the security program is still staffed.

Use the Role AddressBind the key to security@yourdomain, the same address you publish in the Contact field. Researchers cross-check the key's user ID against the contact — a mismatch looks suspicious.

Step 2 — Export and Publish the Public Key

Export the public key in ASCII-armored form:

bash
gpg --armor --export security@example.com > pgp-key.txt

Host pgp-key.txt on your website over HTTPS and reference it from the Encryption field of your security.txt. This one URL serves two purposes: researchers use the key to verify your signature and to encrypt reports they send you.

text
Encryption: https://example.com/pgp-key.txt

Step 3 — Write the Unsigned File

Prepare your security.txt with at least Contact and Expires — the Security.txt Generator builds a valid one in seconds. Make sure the Encryption field points at the key you just published:

text
Contact: mailto:security@example.com Expires: 2027-07-01T00:00:00Z Encryption: https://example.com/pgp-key.txt Canonical: https://example.com/.well-known/security.txt

Step 4 — Cleartext-Sign the File

A cleartext signature wraps the file so it stays human-readable while carrying the signature inline — exactly the form RFC 9116 expects:

bash
gpg --clearsign --local-user security@example.com security.txt mv security.txt.asc security.txt

The signed result looks like this and is what you deploy:

text
-----BEGIN PGP SIGNED MESSAGE----- Hash: SHA512 Contact: mailto:security@example.com Expires: 2027-07-01T00:00:00Z Encryption: https://example.com/pgp-key.txt Canonical: https://example.com/.well-known/security.txt -----BEGIN PGP SIGNATURE----- iHUEARYKAB0WIQT... -----END PGP SIGNATURE-----
Re-sign on Every ChangeAny edit to the file — even fixing a typo — invalidates the signature. Re-run gpg --clearsign after every change, and always when you re-issue the file before its Expires date. Editing the deployed file in place without re-signing is worse than not signing at all: a broken signature actively signals tampering.

Step 5 — Deploy and Verify

Upload the signed file to /.well-known/security.txt, served as text/plain; charset=utf-8 over HTTPS. Then verify the signature the same way a researcher would:

bash
# Import the published key and verify the live file curl -s https://example.com/pgp-key.txt | gpg --import curl -s https://example.com/.well-known/security.txt | gpg --verify # Expected: gpg: Good signature from "Example Corp Security <security@example.com>"

Finally, run the ShowDNS Security.txt Tester — it detects the cleartext signature and validates every other RFC 9116 requirement (location, Contact, Expires, HTTPS rules) in one pass.

Key Maintenance

  • Back up the private key (gpg --export-secret-keys --armor) to encrypted offline storage — losing it means researchers can no longer verify continuity.
  • Renew before expiry with gpg --quick-set-expire, then re-publish the public key and re-sign the file.
  • Rotate on staff changes if anyone with passphrase access leaves the security team.
  • Consider a hardware token (YubiKey, Nitrokey) so the private key never touches disk on a networked machine.

Related Articles