Skip to content

Instantly share code, notes, and snippets.

@vector623
Last active August 11, 2021 13:52
Show Gist options
  • Save vector623/24ed5792e4a4a6aed4d275d14cf22ff0 to your computer and use it in GitHub Desktop.
Save vector623/24ed5792e4a4a6aed4d275d14cf22ff0 to your computer and use it in GitHub Desktop.
quick primer for devs signing commits in github

Table of Contents

Quick primer for devs trying to sign commits in github

GPG Intro

Gpg stands for GNU Privacy Guard, which is an open source implementation for OpenPGP encryption.

While ssh keypairs are generally used for authenticating to remote systems, gpg is generally used to sign content. Git enables you to sign commits and tags with your private gpg key and GitHub allows you to upload your public gpg key in user settings.

When a signed commit is pushed into GitHub, it will be marked by a 'Verified' tag. You can then apply rules to repo branches to require all commits to be signed. Unsigned commits on a protected branch will be rejected during git push.

GPG Usage

These commands assume a linux environment - either native, vm or wsl.

Git bash will not work here.

Create signing key for git

#create ~/.gnupg by invoking gpg
gpg -k

#create master key, which is only for creating subkeys
gpg --full-generate-key #select RSA (sign only) option

#list your new key (along with any other public keys loaded)
gpg -k

#list your private keys
gpg -K

Example

test@feigas:~$ gpg -K
gpg: /home/test/.gnupg/trustdb.gpg: trustdb created

test@feigas:~$ gpg --full-gen
gpg (GnuPG) 2.1.18; Copyright (C) 2017 Free Software Foundation, Inc.
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.

Please select what kind of key you want:
   (1) RSA and RSA (default)
   (2) DSA and Elgamal
   (3) DSA (sign only)
   (4) RSA (sign only)
Your selection? 4
RSA keys may be between 1024 and 4096 bits long.
What keysize do you want? (3072)
Requested keysize is 3072 bits
Please specify how long the key should be valid.
         0 = key does not expire
      <n>  = key expires in n days
      <n>w = key expires in n weeks
      <n>m = key expires in n months
      <n>y = key expires in n years
Key is valid for? (0)
Key does not expire at all
Is this correct? (y/N) y

GnuPG needs to construct a user ID to identify your key.

Real name: David Gallmeier
Email address: dgallmeier@gmail.com
Comment: gpg key for signing
You selected this USER-ID:
    "David Gallmeier (gpg key for signing) <dgallmeier@gmail.com>"

Change (N)ame, (C)omment, (E)mail or (O)kay/(Q)uit? o
We need to generate a lot of random bytes. It is a good idea to perform
some other action (type on the keyboard, move the mouse, utilize the
disks) during the prime generation; this gives the random number
generator a better chance to gain enough entropy.

Export and backup of keys

You need to export your public key to load it into your github settings and it's a good idea to export the private keys for backup.

#Export public key (use the email address
gpg --armor --output EMAILADDRESS.public.asc --export EMAILADDRESS

#Export private keys (master key + subkeys)
gpg --armor --output EMAILADDRESS.private.asc --export-secret-keys EMAILADDRESS

#Export private keys (subkeys only)
gpg --armor --output EMAILADDRESS.subkeys.asc --export-secret-subkeys EMAILADDRESS

You will upload the contents of EMAILADDRESS.public.asc in GitHub.

Git configuration

GitHub user settings

Exported keys will be in a base64 format, similar to how ssh keys look.

Sample public key:

-----BEGIN PGP PUBLIC KEY BLOCK-----

mQENBFwGwSMBCADqS2vmDuG9TWpOMol7mq1d3opRfZvrpYld6iVrWdj/1I4U9uLo
NtFix4N6iN7XSG4vmQ57Lil9Y+QzJTcoSuG0FCRX5VKNkUSLG9GnafLx10BylfE3
yKppAZnQgg2WaW+XW1ZbfCzdVxsDyA0iWRuzmUZJ7XbWMhB10yRtEzREJnakZcjd
vy4lvajDO6Nbdqb3KkRCbPUPX9fW6blM7FeJ0CpSIsanjYGHnbFKquT5DZM06vN8
ZEzx/OQ0xvPGrcTsUSbyOfkPl8zhpkv5fcEXmh19TxvxWHHBLClOF9oKDa3grlOz
XmQ9HlmxgcJgqfrokxR2zGFa9k6dl8IqPj95ABEBAAG0VkRhdmlkIEdhbGxtZWll
ciAoamVua2lucyBkZXBsb3kga2V5IGZvciBibGFja2JveCkgPGplbmtpbnNAamVu
a2lucy5mZWlnYXMueG91bmdlcy5uZXQ+iQFOBBMBCAA4FiEEgV8yCg4wj197o7g1
vIOv0/ZlMRoFAlwGwSMCGwMFCwkIBwIGFQgJCgsCBBYCAwECHgECF4AACgkQvIOv
0/ZlMRqGUAgAkPK7hO5sOFW1xNONFog3vrL+HMJ52MUsQ1fd5qD5HPZuoGbMKiWf
ClaHGC71euoPtYqr4OEyoeMbOlwPTiNiK+VBb99xP/L5mbExeLGkcpZvSXVUn5D/
nml0sUh2dnNZ1CPdJyyD2iTLWtm+0nMIl0t6FZZoZYGUH6UMHdlgzCaQSTK2Gnu2
do51B8vq+6wnYEF6BFyXjICW2gSX7rFanqhk8bPyYIJT3Qec3S/kcNIsqJUcBux8
XARLICby/0VuhCTk/qiEZ9QugRRV76qgw5B1PMdjK40DVq8pFig5+xUY5PpSM9SD
UnkksTQLNKK6gOaTAPPXJcDA5hbudbpH17kBDQRcBsEjAQgA0LablculL+99NhTa
0Ittp76TCDsgLeYVDmqitI3I9C/Flxr84OinHmw+WOU5WcIS7zJZjO0gJUThNoW8
W9rAWYiSAd7Nix6sguDmUDF6Iu27cMSO0Bh7HNzFV4YCgAHVEvBcS/pmTCbmeub+
GpXtRBTEiT3BXp86453d4Abh1MDh9z1LIeEYy1sbTMDwU0ZfVZWnwcokmEY3qrAy
krJI1XsqeikzQTo53lH6YHYxrJFPozuYOIv/SAEhNQhKnqLFE792N1HYmLct1XTb
mYbbYAdrSRRDnqX1hqGsKM9Y7fNQIPhhFcwHlnpH3f8cRn/4HE0RKyDYOyoQtyAN
Q5aNdwARAQABiQE2BBgBCAAgFiEEgV8yCg4wj197o7g1vIOv0/ZlMRoFAlwGwSMC
GwwACgkQvIOv0/ZlMRrttwf8C4Nhh9RmV0wmo38yqsl2PDL8YP7IDoDKhRKhhDyw
krfByG/PbRLbAMQDe8ZARsvF1nX8JJG03TLTr59HiLjiIYSg5xc4EpWjsW4zYKDL
M9p6FMUzMrXpzVTlHgEgfKnXrTaBVZ7dJohm38w2hoyZd9etQNMzNCDq1KqNSNuf
1tKQVYN4K2VQH69YOvwQiNNYrzyKhydPkgqvemX8Zhdiarwd5/VwS68A+taruLQZ
jnVbctNPrSM6gluMXl4WU8QcObeV3VKmvG620PNgdKqzsUviKpI1RtCzeK/rb6Jr
AhO8Gz4XFSwm3ZxIg5n+7k794Or/NQiELcevviV+0yVyaw==
=+s8M
-----END PGP PUBLIC KEY BLOCK-----

Add this public key to your GitHub account, under User -> Settings -> SSH and GPG keys.

Configure git locally

Add signing key to git's config:

davidg@DESKTOP-53SN5LI:~/gits/studycast$ gpg -k
/home/davidg/.gnupg/pubring.kbx
-------------------------------
pub   rsa2048 2017-10-31 [SC]
      EA40D5B54300BAD17CFB73CEE87C032427B77C9F
uid           [ unknown] David Gallmeier <dgallmeier@gmail.com>
sub   rsa2048 2017-10-31 [E]
sub   rsa2048 2017-10-31 [S]
sub   rsa2048 2017-11-24 [A]
sub   rsa2048 2017-10-31 [A]

davidg@DESKTOP-53SN5LI:~/gits/studycast$ git config --global user.signingkey EA40D5B54300BAD17CFB73CEE87C032427B77C9F
davidg@DESKTOP-53SN5LI:~/gits/studycast$

Sign commits

After you've updated GitHub and git locally, add the -S flag to git commit:

davidg@DESKTOP-53SN5LI:~/gits/studycast$ git commit -m "Signed commit" -S
[master 8d1121a] Signed commit
 1 file changed, 1 insertion(+)

NOTE that if your gitconfig email address matches the address on your gpg key, git may automatically sign commits for you.

Branch protection

  1. In the repository's Settings -> Branches, click Add Rule.
  2. List the branch(es) you want to protect.
    • for multiple branches, you can use wildcards, or add multiple rules
  3. Check 'Require signed commits'
  4. Click Create

Demo output

When things are setup properly, unsigned commits will be rejected when you attempt to push them into github. You will see an error message like this:

test@DESKTOP-53SN5LI:~/studycast$ git push origin master
Counting objects: 6, done.
Delta compression using up to 4 threads.
Compressing objects: 100% (5/5), done.
Writing objects: 100% (6/6), 575 bytes | 0 bytes/s, done.
Total 6 (delta 3), reused 0 (delta 0)
remote: Resolving deltas: 100% (3/3), completed with 2 local objects.
remote: error: GH006: Protected branch update failed for refs/heads/master.
remote: error: Commits must have valid signatures.
To github.com:vector623/studycast.git
 ! [remote rejected] master -> master (protected branch hook declined)
error: failed to push some refs to 'git@github.com:vector623/studycast.git'

Again, remember that commits may be signed automagically by git, if your gitconfig email matches your gpg email.

Locally validate that a commit is signed

To check whether or not a commit has been signed, use git verify-commit.

If you have the public key for the gpg signature loaded locally, you'll see that the signature is good.

davidg@DESKTOP-53SN5LI:/mnt/c/Users/David G/gits/studycast$ git verify-commit 932e890ec92c1da010c1ab50c108fd871df00ccf
gpg: Signature made Thu 06 Dec 2018 11:12:23 AM STD
gpg:                using RSA key 4E6AEDB3630B2E7863415C0A39C8649055B0BCC2
gpg: Good signature from "David Gallmeier <dgallmeier@gmail.com>" [unknown]
gpg: WARNING: This key is not certified with a trusted signature!
gpg:          There is no indication that the signature belongs to the owner.
Primary key fingerprint: EA40 D5B5 4300 BAD1 7CFB  73CE E87C 0324 27B7 7C9F
     Subkey fingerprint: 4E6A EDB3 630B 2E78 6341  5C0A 39C8 6490 55B0 BCC2

Don't worry about the warning for now - that is resolved through assigning trust, which is not necessary for us since we'll be using github to validate that the signature belongs to the owner:

If you do not have the public key loaded, you'll see that the commit has been signed and the key used, but you won't be able to check the signature.

test@DESKTOP-53SN5LI:~/studycast$ git verify-commit 932e890ec92c1da010c1ab50c108fd871df00ccf
gpg: Signature made Thu Dec  6 11:12:23 2018 STD
gpg:                using RSA key 4E6AEDB3630B2E7863415C0A39C8649055B0BCC2
gpg: Can't check signature: No public key

If there is no signature, you'll get blank output:

test@DESKTOP-53SN5LI:~/studycast$ git verify-commit 8a7c03e959b48acc07d2cb01cef3834733c59a8f
test@DESKTOP-53SN5LI:~/studycast$
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment