Skip to content

Instantly share code, notes, and snippets.

@emildimitrov
Last active September 18, 2022 15:48
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save emildimitrov/928c640b3bec2ece579ebe14ffc288db to your computer and use it in GitHub Desktop.
Save emildimitrov/928c640b3bec2ece579ebe14ffc288db to your computer and use it in GitHub Desktop.
Using GPG for GitHub authentication and commit signing

Using GPG for github ssh and commit signing

Generate master key

Master key will be used only for certification - signing certfiicates for subkeys. Sign, Encrypt, Authenticate will be delegated to subkey/s.

Run gpg --expert --full-generate-key

  • Choose RSA (set your own capabilities)
  • Disable sign - type S
  • Disable encrypt - type E
  • Quit & continue - type Q
  • Input 4096 as desired size
  • Setup expiration. I'm setting 0 - never.
  • Construct the user id - input full name and email. leav comment empty.
  • Choose your passphrase

Generate subkey

We'll generate one subkey for sign, encrypt, authenticate - feel free to make separate if you wish

Run gpg --expert --edit-key <email> When in the gpg run addkey

  • Choose RSA (set your own capabilities)
  • Add authenticate - type A
  • Quit & continue - type Q
  • Input 4096 as desired size
  • Setup expiration. I'm setting 0 - its not good practice, but its me :)
  • Now input the passhphrase of the master
  • Save and exit - type save

Configure GPG agent

The below will instruct the agent deamon to start with ssh support and configures the pinentry program for the TTY input. We also set default cache to 1 day

enable-ssh-support
pinentry-program /usr/local/bin/pinentry-curses
default-cache-ttl 86400
max-cache-ttl 86400

How to get pinentry-curses to start on the correct tty?

Configure shell

The below is configuring SSH to use gpg-agent instead of ssh-agent and instructs pinentry-curses to start on the correct tty.

unset SSH_AGENT_PID
if [ "${gnupg_SSH_AUTH_SOCK_by:-0}" -ne $$ ]; then
  export SSH_AUTH_SOCK="$(gpgconf --list-dirs agent-ssh-socket)"
fi
export GPG_TTY=$(tty)
gpg-connect-agent updatestartuptty /bye >/dev/null

Enable GPG authenticate subkey for SSH authentication

In our case we have one subkey, but if you have separate for auth pick it

Get the subkey keygrip To find the keygrip id run gpg --list-keys --with-keygrip Add the keygrip to the list with approved keys echo <keygrip id> >> ~/.gnupg/sshcontrol Verify that this key now is in the ssh identities list with ssh -L

Restart ssh & gpg agents

killall ssh-agent gpg-agent
unset GPG_AGENT_INFO SSH_AGENT_PID SSH_AUTH_SOCK
eval $(gpg-agent --daemon --enable-ssh-support)

Add GPG key to github for authentication

Now we need to export to ssh format our public key (ssh key) and add it to github as SSH authentication key. Run gpg --export-ssh-key <key id/email> Now get the result and paste it in github as authentication key.

Test that the key is working with your github account ssh -T git@github.com

Enable git commit signing

Get the key id of your subkey gpg --list-secret-keys --keyid-format long - the id is after the rsa4096/ Now export this key in ASCII armor gpg --armor --export Add it ass new GPG key to github.

Configure git to use this key to sign commits git config --global user.signingkey <key id>! Note that the ! in the end is important to force always to use this key.

Optionally enable git to always sign commits git config --global commit.gpgsign true

Now to test sign some commit git commit -a -S -m 'Signed commit' Check the commit signature git log --show-signature -1 You should see good signature confirmation.

Also note that in order to display verified badge in github the GPG key email & the commit email should be the same and the email address to be verified.

Backup and remove master key

To stay safe if things go wrong we'll operate with offline master key (not present).

Export the secret master gpg -a --export-secret-keys > master-secret-key.gpg

Export secret subkeys gpg -a --export-secret-subkeys > sub-secret-keys.gpg

Delete key and subkeys gpg --delete-secret-key <id>

Import the subkeys gpg --import sub-secret-keys.gpg

Verify that keys are not with offline master gpg -K You should see sec# the # indicates that this is offline.

Setup on new machine

In case you have new machine and you want to use your backed up keys

gpg --import master-secret-key.gpg gpg --import sub-secret-keys.gpg

Verify keys are there by gpg -K

You will notice that it says [undefined] for the key trust

To give trust to you imported keys gpg --edit-key <id/email> type trust choose ultimate trust type save

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment