# Yubikey + GPG + Github + Keybase The following guide are steps that can be used to generate GPG keys on a YubiKey, use the gpg keys to sign github commits, and publish the public gpg key to Keybase. Why is this a good idea? 1. Generating and storing GPG keys on a YubiKey allows the private key to be protected and ported between physical machines. 1. Signing git commits adds an extra layer of verification that code changes originated from an trusted source. 1. Using a YubiKey + touch-to-sign requires a physical presence to use the GPG signing key. 1. GitHub supports restricting commits to a repo to only those that are signed. 1. Putting a physical stamp on your code commits invokes a feeling of pride. ## Install required programs to generate GPG keys 1. Install gpg tools ``` $ brew install gpg ``` 1. Install pinentry for mac ``` $ brew install pinentry-mac ``` 1. Set pinentry in gpg config ``` $ echo "pinentry-program /usr/local/bin/pinentry-mac" >> ~/.gnupg/gpg-agent.conf ``` 1. Kill the current gpg agent to pick up the change. ``` $ killall gpg-agent ``` ## Edit GPG settings on the YubiKey 1. Connect Yubikey to laptop. 1. Disregard keyboard setup wizard if one tries to recognize the YubiKey. 1. Use gpg to connect to the opengpg app on the Yubikey. ``` $ gpg --edit-card ``` 1. Switch to admin mode of the Yubikey. ``` gpg> admin ``` 1. Change the Yubikey to generate gpg keys of 4096 bits instead of 2048. ``` gpg> key-attr ``` 1. For **Signature key**, **Encryption key**, and **Authentication key** do the following. Select 1 to use RSA keys. ``` (1) RSA ``` 1. Enter: ``` 4096 ``` 1. At the prompt for the admin pin enter: ``` 12345678 ``` 1. Set the admin pin for the card. ``` passwd ``` 1. Select 3 to set the admin pin. ``` 3 ```` 1. Enter the default admin pin. ``` 12345678 ``` 1. Enter a new admin pin twice. **Be sure to save this pin in a secure place** 1. Next, change the user pin. ``` 1 ``` 1. Enter the default user pin. ``` 1234567 ``` 1. Enter a new user pin twice. **Be sure to save this pin in a secure place** 1. Next, set the Reset pin. ``` 4 ``` 1. Enter your admin pin. 1. Enter a new Reset pin. **Be sure to save this pin in a secure place** 1. Select `Q` to quit the pin menu. 1. (Optional) Set your name and email on the card. ``` gpg> name ``` ## Create GPG keys on the YubiKey 1. From the `gpg>` prompt, generate GPG keys. ``` gpg> generate ``` 1. Do not make an off-card backup of encryption key ``` n ``` 1. Set the expiration date for the keys to 16 years ``` 16y ``` 1. Enter your name and e-mail address. 1. Enter `O` for `Okay` 1. **Generating the keys may take several minutes.** The YubiKey will blink while keys are generated. During this time, move your mouse and type on the keyboard. This will help with generating random bytes. Without enough random activity, the key generation will fail. 1. After some time (5-10 minutes) you should see `public and secret key created and signed`. 1. `quit` 1. If you log back into the card `gpg --edit-card`, you should see the details of the new keys displayed. You can also display the info using the `list` command. ## Configure Pin retries and touch to sign on the Yubikey 1. Install the yubikey manager app ``` brew install ykman ``` 1. Use ykman to turn on touch to sign functionality. ``` ykman openpgp set-touch SIG ON ``` 1. Enter the admin PIN to allow modifying the touch setting. 1. Answer yes (y) to `Set touch policy of signature key to on?` 1. Use ykman to set pin retries (5 tries for user pin, reset pin, admin pin) ``` ykman openpgp set-pin-retries 5 5 5 ``` 1. Enter the admin PIN to allow modifying the retries setting. 1. Answer yes (y) to `Set PIN retry counters to: 5 5 5?` ## Test your new signing key 1. Test by signing a string on the cli. You should be prompted in a pop-up window to enter your YubiKey User PIN. **Remember to touch the yubikey with your finger when blinking to sign the message** ``` echo "foobar" | gpg --sign --armor | gpg --decrypt ``` ## Add your public GPG key to Github 1. Import your public gpg key to github. ``` gpg -k # get fingerprint of key to export. This will be a string of characters one line below the line that starts with pub, and one line above the line that starts with uid. gpg --armor --export $FINGERPRINT | pbcopy ``` Reference: [Adding a new GPG key to your GitHub account](https://help.github.com/en/github/authenticating-to-github/adding-a-new-gpg-key-to-your-github-account) 1. Update your gitconfig to use the new gpg key to sign. ``` git config --global commit.gpgsign true git config --global user.signingkey $FINGERPRINT ``` When you make a git commit, you *may* be propmted to enter the user pin of the yubikey to unlock it. *Each* time you make a git commit, the commit will require access to your private gpg key to sign. You will need to physically touch the yubikey to grant access. Otherwise your commit will timeout and fail. To see the signature of your commit, use the following command: ``` git log --show-signature ``` ## Import and trust GitHub's Public GPG key 1. Import Github's public key into local gpg keychain ``` curl https://github.com/web-flow.gpg | gpg --import ``` 1. Show Github's key ``` gpg -k ``` 1. Edit Github's key to change the level of trust ``` gpg --edit-key $GITHUB_PGP_KEY_FINGERPRINT ``` 1. Change the trust level ``` gpg> trust ``` 1. Enter the level of trust you have for the key (1-5) ``` Your decision? 3 ``` 1. Sign Github's key with your gpg public key ``` gpg> 1 # select the key to sign (* should appear next to the key name) gpg> sign ... Really sign? (y/N) y ``` 1. Save and quit ``` save ``` 1. Show keys to confirm GitHub's key is signed and has full trust ``` gpg -k ``` ## (Optional) Setup Keybase with new GPG Public key and prove identity with Github 1. Install Keybase ``` brew install keybase ``` 1. Signup for a keybase account but do not import keys. ``` keybase signup ``` 1. Add your public gpg key to keybase ``` keybase pgp select ``` 1. Set the keybase account passphrase. ``` keybase passphrase set ``` 1. Add your keybase identity proof to github ``` keybase prove github ```