Using Keybase pgp keys for github gpg verification

September 28, 2017

I recently started using the excellent keybase.io app for encrypted chat and all the crypto goodness motivated me to finally set up gpg verified commits on Github. I started with this helpful article: Github GPG + Keybase PGP which I recommend you take a look at, but I had to do a few more steps that I wanted to document.

Installing Keybase

Keybase is easy to install: keybase.io/download. For arch, it was a simple install and setup:

packer -S keybase-bin  
run_keybase

Once installed, you’ll need to start up the app and create an account if you haven’t already.

Generate a key

Generate a new key with keybase, and upload it to your profile. Alternatively, use keybase pgp select to use your an existing key. To use this key for Github verified commits, it will need to have the same email as on your Github account.

$ keybase pgp gen

Export your keybase secret key to your gpg keyring:

$ keybase pgp export -s -p | gpg --allow-secret-key-import --import --

List keys in your gpg keyring and locate your keybase key

$ gpg --list-secret-keys --keyid-format LONG
/home/jay/.gnupg/pubring.kbx
----------------------------
sec   rsa4096/C17228D898051A91 2017-01-30 [SC]
      326DA75610069B5DECA8D2DDC17228D898051A91
uid                 [ultimate] Jay Baker 
ssb   rsa4096/7C87801D5E56F673 2017-01-30 [E]

sec   rsa4096/C24CD98AB0900706 2017-09-28 [SC] [expires: 2033-09-24]
      F21FC721B22B0C176BAFBE35C24CD98AB0900706
uid                 [unknown] Jay Baker 
uid                 [unknown] Jay Baker 
ssb   rsa4096/4599729752E8D5C4 2017-09-28 [E] [expires: 2033-09-24]

I have two keys here, the second one is the one I made with keybase pgp gen. We want to grab the keyid string from the second line:

sec   rsa4096/C24CD98AB0900706 2017-09-28 [SC] [expires: 2033-09-24]
C24CD98AB0900706=

Let’s set a trust level for our key. Since we just made it, we can give it full trust.

$ gpg --edit-key C24CD98AB0900706
gpg (GnuPG) 2.2.1; 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.

Secret key is available.

sec  rsa4096/C24CD98AB0900706
     created: 2017-09-28  expires: 2033-09-24  usage: SC  
     trust: unknow      validity: unknown
ssb  rsa4096/4599729752E8D5C4
     created: 2017-09-28  expires: 2033-09-24  usage: E   
[unknown] (1). Jay Baker 
[unknown] (2)  Jay Baker 

gpg> trust

Please decide how far you trust this user to correctly verify other users' keys
(by looking at passports, checking fingerprints from different sources, etc.)

  1 = I don't know or won't say
  2 = I do NOT trust
  3 = I trust marginally
  4 = I trust fully
  5 = I trust ultimately
  m = back to the main menu

Your decision? 5
Do you really want to set this key to ultimate trust? (y/N) y

sec  rsa4096/C24CD98AB0900706
     created: 2017-09-28  expires: 2033-09-24  usage: SC  
     trust: ultimate      validity: ultimate
ssb  rsa4096/4599729752E8D5C4
     created: 2017-09-28  expires: 2033-09-24  usage: E   
[ultimate] (1). Jay Baker 
[ultimate] (2)  Jay Baker 

gpg> quit

Now we can decide to do global or per repository signing with git. This step is optional, you can always manually sign commits with git -S or git --gpg-sign on a per commit basis.

$ git config commit.gpgsign true

This is per repository, add a --global flag after config if you want to enable gpg signing globally for git. If we change our minds later and want to disable signing just run the same command but with false. Also, if want to do just do a single commit without signing:

$ git --no-gpg-sign commit

Now let’s tell git which gpg key to use:

$ git config user.signingkey C24CD98AB0900706 # per repository

Again, add a --global flag if you want.

To verify that our commit worked:

$ git log --show-signature
commit 1f10113fadeae03fd8de870fb18c8563d0b3c602 (HEAD -> master)
gpg: Signature made Thu 28 Sep 2017 17:23:20 EDT
gpg:                using RSA key F21FC721B22B0C176BAFBE35C24CD98AB0900706
gpg: Good signature from "Jay Baker " [ultimate]
gpg:                 aka "Jay Baker " [ultimate]
Author: Jay Baker 
Date:   Thu Sep 28 17:23:20 2017 -0400
	detailed commit message goes here

Add our key to Github

Finally, we need to add our key to Github. Remember, your key will need the same email as your Github user email. You can add more email addresses to your key with gpg --edit-key and then the adduid command.

Let’s get our public key from keybase:

$ keybase pgp export
-----BEGIN PGP PUBLIC KEY BLOCK-----

mQINBFnNUb8BEAC3RGNiW3AYUIxAsrQBRfclM65naI/xGlvRju6b5tuoZ33Qbvnq
...
WB+E6/rYlZG4Vdk2W1bTk0R2iAVHoamZD0PmJAkv46SiuHqeyOdBGAGsgdVo1FGa
Gw==
=sE0m
-----END PGP PUBLIC KEY BLOCK-----

Copy that, and head to https://github.com/settings/keys, click “New GPG key”, paste it in, then click “Add GPG key” to save it. verifi

That’s it! You can now have verified commits on Github with your keybase pgp key!

Tags

Color Bash Prompt (PS1) with git Integration

December 11, 2015

You’ve seen it in screenshots and guides around the net: colorful custom bash prompts with useful info like what branch you’re currently in and if there are any uncommitted changes. Let’s learn how to make our own custom prompt with git integration!

Screenshot from 2015-12-11 18-17-28

git

Obviously, you will need git installed for this to work. But if you didn’t already use git, then you probably wouldn’t be reading this post so … Anyway, in order for us to add git info to our PS1, we’ll need to find the git-prompt.sh script on your system. On Fedora, it’s located at /usr/share/git-core/contrib/completion/git-prompt.sh, but on Arch it’s at /usr/share/git/completion/git-prompt.sh. If it’s not in either location, then just use the locate command to find it:

sudo updatedb && locate git-prompt.sh

~/.bashrc

Bash looks in a few different places for customizations, but the best place to put yours is usually your ~/.bashrc file. Anything in this file will sourced by Bash when you open a new shell or terminal window. The ~/.bashrc is specific to your user. Other user accounts on the system (like root) won’t source your user’s .bashrc. Learning your way around the .bashrc file is an essential skill for any Linux power-user. There is a lot you can do with it, but we’ll just focus on the PS1, aka the bash prompt.

Most distributions have a simple, default PS1, usually something like this:

user@host $ 

Note: The $ usually indicates that this is an unprivileged user, whereas # denotes the root user

That’s a serviceable prompt, but Bash allows you to customize it to your heart’s content. I’m only going to cover my personal PS1 in this post. If you want something tailored just for your needs and want to create your own custom bash prompt, then a good place to start is the Arch wiki: Color Bash Prompt.

If you just want to use my PS1, then comment out your current PS1 (in case you don’t like the new one and want to go back) and paste the following into your ~/.bashrc

# Simple PS1
#PS1='(\u:\h), \W, '

# Change this to the location of git-prompt.sh on your distribution.
source /usr/share/git-core/contrib/completion/git-prompt.sh

# Creates the bash_prompt function
bash_prompt () {

# Checks to see if the current directory is a git repo or not
gitcheck_branch="$(git branch &>/dev/null; if [ $? -eq 0 ]; then echo "yes"; else echo "no"; fi)"

if [ $gitcheck_branch == "yes" ];
then
        # If we are in a git repo, then check to see if there are uncommitted files
        gitcheck_status="$(git status | grep "nothing to commit" > /dev/null 2>&1; if [ $? -eq 0 ]; then echo "clean"; else echo "unclean"; fi)"

	if [ $gitcheck_status == "clean" ];
	then
                # If there are no uncommitted files, then set the color of the git branch name to green
		git_prompt='\[\033[0;32m\]$(__git_ps1)'
	else
                # If there are uncommitted files, set it to red.
		git_prompt='\[\033[0;31m\]$(__git_ps1)'
	fi
else
        # If we're not in a git repo, then display nothing
	git_prompt=""
fi

# This is what actually sets our PS1. The ${git prompt} is what will display our git status.
PS1="\[\e[0;36m\]┌─\[\e[1;37m\][\u@\h]\[\e[0m\]\[\e[0;36m\]─\[\e[0;93m\](\w)${git_prompt} \n\[\e[0;36m\]└─\[\e[1;32m\][\A]\[\e[0m\]\$(if [[ \$? == 0 ]]; then echo \"\[\033[0;32m\]$\"; else echo \"\[\033[0;31m\]$\"; fi)\[\033[00m\] "

}
# PROMPT_COMMAND is run just before the PS1 is printed. We've set it to run our bash_prompt function.
PROMPT_COMMAND=bash_prompt

The key to all of this working is the PROMPT_COMMAND. Bash will execute whatever the PROMPT_COMMAND is set to just before it prints the PS1, in other words, every time you open a new shell, execute any command yourself, or even just hit the enter key. With the above in your .bashrc, Bash will check to see if the present working directory is a git repo or not. If it is, it will check to see if there are uncommitted files. If there are no uncommitted files, it will append the branch name in green after the working directory in our PS1. If there are uncommitted files, it will append the branch name in red. If the working directory isn’t a git repo, then it will print nothing after the working directory in the PS1.

Oh, I almost forgot to mention. There’s another neat little trick in here that I really appreciate:

\$(if [[ \$? == 0 ]]; then echo \"\[\033[0;32m\]$\"; else echo \"\[\033[0;31m\]$\"; fi)\[\033[00m\]

This bit will check the exit code of last executed command. If it’s zero (successful), then the $ will be green. If the command failed, the $ will be red. Can be handy for commands that don’t tell you whether they succeeded or not.

Screenshot from 2015-12-11 18-18-32

There are of course, other ways to implement something like this. A quick google search will turn up plenty of guides for doing it differently. But ultimately, this is the method that works the best for me. It’s also quite versatile. Having PROMPT_COMMAND call a function that sets the PS1 allows you to do all kinds of conditionals on what your PS1 will look like. You could have different colors for different times of the day, A status indicator for whether you’re connected over ssh or through a local terminal emulator (useful if you have the same .bashrc on all of your remote machines), an indicator for whether you’re connected to your vpn or not. Anything you can do with a bash script, you can put in your PS1.

Tags