Sign a commit with GPG key

Chanming
Dec 19, 2019

Generate a new GPG key

install gpg and/or gpg2 on ubuntu system by:

sudo apt-get install gpg gnupg2

To avoid problems, install gpg2 instead of gpg according to this and this.

Then we can generate a GPG key pair by:

gpg --default-new-key-algo rsa4096 --gen-key # if your gpg version < 2.1.17
gpg --full-generate-key # if your gpg version is ge 2.1.17

This command will prompt you with some questions asking you about your name, email, passphrase and some other key characteristics. You can keep those default settings but you need to make sure your key size is at least 4096. Do remember that this information you provide need to match the public information on your Github. In other words, if you have set your email to be private, invisible to others, you then need to fill your no-reply email address in this step. eg : abcdefg__yourusrname@github.com. If you ‘ve set your personal email address public, then you need to fill it instead. So for short, you should provide the information which matches your public displayed commit information. The passphrase will be required for future signing process when you make a commit, so do remember this passphrase.

After generation process, you can use the command below to check your generated key:

gpg --list-secret-keys --keyid-format LONG

From the returned information, you will find all the key pairs generated by gpg program in a format like:

/home/username/.gnupg/pubring.kbx
----------------------------------
sec   rsa4096/AAAAAAAAAAAAAAAA 2020-04-28 [SC] [expires: 2021-04-28]
      57C5F8CF74DE7A3DC1DE6BF238A38CCF075BFCDD
uid                 [ultimate] your_signed_name <YOUR EMAIL1>
ssb   rsa4096/BBBBBBBBBBBBBBBB 2020-04-28 [E] [expires: 2021-04-28]

sec   rsa3072/AAAAAAAAAAAAAAAA 2020-04-28 [SC] [expires: 2022-04-28]
      57C5F8CF74DE7A3DC1DE6BF238A38CCF075BFCDD
uid                 [ultimate] your_signed_name <YOUR EMAIL2>
ssb   rsa3072/BBBBBBBBBBBBBBBB 2020-04-28 [E] [expires: 2022-04-28]

sec   rsa4096/AAAAAAAAAAAAAAAA 2020-04-28 [SC] [expires: 2022-04-28]
      57C5F8CF74DE7A3DC1DE6BF238A38CCF075BFCDD
uid                 [ultimate] your_signed_name  <YOUR EMAIL3>
....

here you will see three sections as sec , uid and ssb for a single key pair. Hence you can interpret that in the example above, there are three key pairs listed. Copy the key ID, which is AAAAAAAAAAAAAAAA in the example above.

set the git program properly

Then we can set the git client to sign future commit using the key we generated before. Type the following command :

git config --global gpg.program gpg2 # set gpg2 as default signing program
git config --global user.signingkey <AAAAAAAAAAAAAAAA>  # HERE PASTE YOUR KEY ID excluding '<' and '>'
git config --global commit.gpgsign true # toggle the switch

Set the Github GPG public key

You then need to export the public key to your Github account. Type the following command in your CLI:

gpg --armor --export <AAAAAAAAAAAAAAAA> # return your public key
# or you can export to file as below
gpg --armor --export <AAAAAAAAAAAAAAAA> > gpg-key.txt # export to gpg-key.txt

You will then get a key content starting with ——BEGIN PGP PUBLIC KEY BLOCK—— and ending with——END PGP PUBLIC KEY BLOCK——. Copy the public key content include those header and footer to your Github GPG settings. Then you can signing your commit using your GPG key.

Troubleshoot

gpg failed to sign the data

  • Remember to set gpg2 as the signing program for git client (instead of gpg).
  • Run echo "text" | gpg2 --clearsign to make sure gpg2 itself works properly. You will be asked for your passphrase to signing the text. After execution, you will see a signed text with ——BEGIN PGP SIGNED MESSAGE—— and ——BEGIN PGP SIGNATURE——. You may encounter with Inappropriate ioctl for device in this step, check the following section for a quick fix.
  • Other test cases you may wanna try if it still doesn’t work: https://stackoverflow.com/a/41054093

Inappropriate ioctl for device

You need to set a environment variable to get it working, type the following command:

GPG_TTY=$(tty)
export GPG_TTY

Write these two lines to ~/.profile , you can then avoid typing these commands every time you start a session. This profile only affect your current user, and will be executed every time you start a remote console. If you would like to apply this system-wide, you can write these lines to /etc/environment .

Change your key passphrase

gpg --edit-key <AAAAAAAAAAAAAAAA>

At the gpg prompt type:

passwd

Type in the current passphrase when prompted.

Type in the new passphrase twice when prompted.

Type:

save

Reference

https://help.github.com/en/github/authenticating-to-github/generating-a-new-gpg-key

https://gist.github.com/ankurk91/c4f0e23d76ef868b139f3c28bde057fc

https://unix.stackexchange.com/a/257065

https://stackoverflow.com/a/41054093