Skip to content

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>.asc
  • privatekey.<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:

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.