PGP¶
Here’s a ready-to-drop MkDocs page based on exactly what you just did (Proton → GPG → GitHub signing → Keybase), including the gotchas you hit.
PGP: Proton → GnuPG → GitHub commit signing → Keybase¶
This guide documents the working setup to use a single Proton-generated PGP key across: - Proton Mail (encryption + signing) - GitHub (signed commits “Verified”) - Keybase (PGP identity / encryption)
It is based on a real setup on Linux (GnuPG 2.4.x, Keybase CLI).
Prerequisites¶
Install tools:
sudo apt update
sudo apt install -y gnupg pinentry-curses
# keybase CLI installed separately (snap/package/manual)
````
Useful environment (for server shells / SSH):
```bash
export GPG_TTY=$(tty)
echo 'export GPG_TTY=$(tty)' >> ~/.bashrc
1) Export your Proton PGP keys¶
In Proton settings (Encryption & Keys), download:
- Public key (.asc)
- Private key (.asc)
Store them safely (example location):
mkdir -p /mnt/export2061/vulcan/.pgp
# Copy downloaded files into /mnt/export2061/vulcan/.pgp
Example file names from Proton look like:
publickey.<email>-<fingerprint>.ascprivatekey.<email>-<fingerprint>.asc
2) Import Proton keys into GnuPG¶
Import public key:
gpg --import /mnt/export2061/vulcan/.pgp/publickey.footballmap@proton.me-87fcd6b79e778f709abf2afc85e1c067e8f55e14.asc
Import private key:
gpg --import /mnt/export2061/vulcan/.pgp/privatekey.footballmap@proton.me-87fcd6b79e778f709abf2afc85e1c067e8f55e14.asc
Verify secret keys:
gpg --list-secret-keys --keyid-format=long footballmap@proton.me
Example expected output for Proton modern keys:
sec ed25519/... [SC]ssb cv25519/... [E]
Also record the full fingerprint (you will use it everywhere):
gpg --fingerprint footballmap@proton.me
3) Mark the Proton key as trusted (local trustdb)¶
Edit the key (use your key ID shown by gpg --list-secret-keys):
gpg --edit-key 85E1C067E8F55E14
Inside gpg>:
trust
5
y
save
Re-check:
gpg --list-secret-keys footballmap@proton.me
4) Configure Git to sign commits with OpenPGP (GPG)¶
IMPORTANT: gpg.format=ssh breaks this¶
If you have gpg.format=ssh, Git expects an SSH public key file path as
user.signingkey. If you set a GPG key ID/fingerprint while gpg.format=ssh,
you’ll see:
Couldn't load public key ... No such file or directory
Fix: force OpenPGP.
Configure (repo-local)¶
cd /mnt/export2061/.dev/fmio
git config --local gpg.format openpgp
git config --local gpg.program /usr/bin/gpg
git config --local user.signingkey 87FCD6B79E778F709ABF2AFC85E1C067E8F55E14
git config --local commit.gpgsign true
(Optional) configure identity for this repo:
git config --local user.name "footballmap.io"
git config --local user.email "footballmap@proton.me"
Test signing:
export GPG_TTY=$(tty)
echo test > test-gpg-sign.txt
git add test-gpg-sign.txt
git commit -m "test signed commit"
git log --show-signature -1
Expected:
using EDDSA key <fingerprint>Good signature from ...
Configure (global)¶
git config --global gpg.format openpgp
git config --global gpg.program /usr/bin/gpg
git config --global user.signingkey 87FCD6B79E778F709ABF2AFC85E1C067E8F55E14
git config --global commit.gpgsign true
5) Add your Proton public key to GitHub (so commits show “Verified”)¶
Export public key:
gpg --armor --export 87FCD6B79E778F709ABF2AFC85E1C067E8F55E14
Copy the entire block to:
GitHub → Settings → SSH and GPG keys → New GPG key
Then push a signed commit and GitHub will show Verified.
6) Fix GH007 “push would publish a private email address”¶
If you push commits using a private email (like footballmap@proton.me) and
GitHub account protection is enabled, you will get:
GH007: Your push would publish a private email address.
Fix options:
Option A (recommended): use GitHub noreply email + rewrite commit¶
Set repo email to GitHub noreply:
cd /mnt/export2061/.dev/fmio
git config --local user.email "<YOUR_GITHUB_ID>+<YOUR_USERNAME>@users.noreply.github.com"
Rewrite the last commit author email:
git commit --amend --reset-author --no-edit
Push with lease:
git push --force-with-lease
Option B: allow the email in GitHub Settings¶
GitHub → Settings → Emails:
- make the email public, or
- disable “Block command line pushes that expose my email”
Then git push works without rewriting history.
7) Import Proton key into Keybase¶
Keybase imports a PGP secret key via --infile.
keybase pgp import \
--infile /mnt/export2061/vulcan/.pgp/privatekey.footballmap@proton.me-87fcd6b79e778f709abf2afc85e1c067e8f55e14.asc
When prompted:
- Enter the passphrase that protects the Proton-exported private key file (NOT your Keybase password).
Verify both keys are present:
keybase pgp list
8) Make Proton key the only active Keybase PGP key¶
Keybase does not have pgp set-primary. Instead you “drop” the old key from
Keybase account usage.
IMPORTANT: keybase pgp drop wants the Keybase Key ID (KID), not the PGP fingerprint¶
From keybase pgp list, you’ll see:
Keybase Key ID: 01...PGP Fingerprint: ...
keybase pgp drop expects the Keybase Key ID (the 01... value).
Example:
keybase pgp drop 0101794da5a8b34f089b10d2b1b5e992b122f378e7cf77dae8bcbbfdb49000c7fea30a
Verify:
keybase pgp list
At this point only the Proton key should remain, and it becomes the effective primary.
Troubleshooting¶
GPG can’t prompt for passphrase / hangs¶
Make sure:
export GPG_TTY=$(tty)
Also ensure a pinentry exists:
command -v pinentry-curses || sudo apt install -y pinentry-curses
Git says it can’t load your “public key … No such file or directory”¶
You likely have gpg.format=ssh.
Check:
git config --show-origin --get gpg.format
Fix:
git config --local gpg.format openpgp
Keybase pgp drop says “KID wrong length”¶
You passed a PGP fingerprint. Use the Keybase Key ID (KID) from:
keybase pgp list
Reference fingerprints (example)¶
-
Proton key (recommended modern):
-
Fingerprint:
87FCD6B79E778F709ABF2AFC85E1C067E8F55E14 - sec:
ed25519(signing) -
ssb:
cv25519(encryption) -
Legacy Keybase-generated RSA:
-
Fingerprint:
585EDA39D3AE938B7B3F54C4DBDD765D05D16E77 - Usually safe to keep locally, but drop from Keybase account usage.