├── img ├── pinentry.png └── gpg-preferences.png └── README.md /img/pinentry.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pstadler/keybase-gpg-github/HEAD/img/pinentry.png -------------------------------------------------------------------------------- /img/gpg-preferences.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pstadler/keybase-gpg-github/HEAD/img/gpg-preferences.png -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Set up Keybase.io, GPG & Git to sign commits on GitHub 2 | 3 | This is a step-by-step guide on how to create a GPG key on [keybase.io](https://keybase.io), adding it to a local GPG setup and use it with Git and GitHub. 4 | 5 | Although this guide was written for macOS, most commands should work in other operating systems as well. 6 | 7 | There's a [video](https://www.youtube.com/watch?v=4V-7KnhcrbY) published by [Timothy Miller](https://github.com/tjacobdesign) explaining some parts of this guide. [Discussion](https://news.ycombinator.com/item?id=12289481) on Hacker News. 8 | 9 | > **Note**: If you **don't** want to use Keybase.io, follow [this guide][1] instead. 10 | > For manually transferring keys to different hosts, check out this [answer on Stack Overflow][2]. 11 | 12 | [1]: https://help.github.com/articles/generating-a-new-gpg-key/ 13 | [2]: https://stackoverflow.com/a/3176373/571227 14 | 15 | ## Requirements 16 | 17 | ```sh 18 | $ brew install gpg 19 | $ brew install --cask keybase 20 | ``` 21 | 22 | You should already have an account with Keybase and be signed in locally using `$ keybase login`. In case you need to set up a new device first, follow the instructions provided by the keybase command during login. 23 | 24 | Make sure your local version of Git is at least 2.0 (`$ git --version`) to automatically sign all your commits. If that's not the case, use Homebrew to install the latest Git version: `$ brew install git`. 25 | 26 | ## Create a new GPG key on keybase.io 27 | 28 | ```sh 29 | $ keybase pgp gen --multi 30 | # Enter your real name, which will be publicly visible in your new key: Patrick Stadler 31 | # Enter a public email address for your key: patrick.stadler@gmail.com 32 | # Enter another email address (or when done): 33 | # Push an encrypted copy of your new secret key to the Keybase.io server? [Y/n] Y 34 | # ▶ INFO PGP User ID: Patrick Stadler [primary] 35 | # ▶ INFO Generating primary key (4096 bits) 36 | # ▶ INFO Generating encryption subkey (4096 bits) 37 | # ▶ INFO Generated new PGP key: 38 | # ▶ INFO user: Patrick Stadler 39 | # ▶ INFO 4096-bit RSA key, ID CB86A866E870EE00, created 2016-04-06 40 | # ▶ INFO Exported new key to the local GPG keychain 41 | ``` 42 | 43 | ## Set up Git to sign all commits 44 | 45 | ```sh 46 | $ gpg --list-secret-keys --keyid-format LONG 47 | # /Users/pstadler/.gnupg/secring.gpg 48 | # ---------------------------------- 49 | # sec 4096R/E870EE00 2016-04-06 [expires: 2032-04-02] 50 | # uid Patrick Stadler 51 | # ssb 4096R/F9E3E72E 2016-04-06 52 | 53 | $ git config --global user.signingkey E870EE00 54 | $ git config --global commit.gpgsign true 55 | ``` 56 | 57 | ## Add public GPG key to GitHub 58 | 59 | ```sh 60 | $ open https://github.com/settings/keys 61 | # Click "New GPG key" 62 | 63 | # We can then use `export` with the `-q` or query flag to match on our key (the first 16 characters should do..) 64 | $ keybase pgp export -q CB86A866E870EE00 | pbcopy # copy public key to clipboard 65 | # Paste key, save 66 | ``` 67 | 68 | ## Import key to GPG on another host 69 | 70 | ```sh 71 | $ keybase pgp export 72 | # ▶ WARNING Found several matches: 73 | # user: Patrick Stadler 74 | # 4096-bit RSA key, ID CB86A866E870EE00, created 2016-04-06 75 | 76 | # user: keybase.io/ps 77 | # 4096-bit RSA key, ID 31DBBB1F6949DA68, created 2014-03-26 78 | 79 | $ keybase pgp export -q CB86A866E870EE00 | gpg --import 80 | $ keybase pgp export -q CB86A866E870EE00 --secret | gpg --allow-secret-key-import --import 81 | ``` 82 | 83 | After importing you probably want to locally trust your own key, otherwise you will see 84 | `gpg: WARNING: This key is not certified with a trusted signature!` when running `git log --show-signature`. 85 | 86 | ``` 87 | $ gpg --edit-key CB86A866E870EE00 88 | gpg> trust 89 | 90 | Please decide how far you trust this user to correctly verify other users' keys 91 | (by looking at passports, checking fingerprints from different sources, etc.) 92 | 93 | 1 = I don't know or won't say 94 | 2 = I do NOT trust 95 | 3 = I trust marginally 96 | 4 = I trust fully 97 | 5 = I trust ultimately 98 | m = back to the main menu 99 | 100 | Your decision? 5 101 | Do you really want to set this key to ultimate trust? (y/N) y 102 | 103 | gpg> quit 104 | ``` 105 | 106 | ## Troubleshooting: `gpg failed to sign the data` 107 | 108 | If you cannot sign a commit after running through the above steps, and have an error like: 109 | 110 | ```sh 111 | $ git commit -m "My commit" 112 | # error: gpg failed to sign the data 113 | # fatal: failed to write commit object 114 | ``` 115 | 116 | You can run `echo "test" | gpg --clearsign` to find the underlying issue. 117 | 118 | If the above succeeds without error, then there is likely a configuration problem that is preventing git from selecting or using the secret key. Confirm that your gitconfig `user.email` matches the secret key that you are using for signing. 119 | 120 | Another solution is set up Git to use GPG program on Windows 121 | ```sh 122 | $ git config --global user.signingkey E870EE00 123 | $ git config --global commit.gpgsign true 124 | $ git config --global gpg.program "C:\Program Files (x86)\GnuPG\bin\gpg.exe" 125 | ``` 126 | 127 | ## Optional: Set as default GPG key 128 | 129 | ```sh 130 | $ $EDITOR ~/.gnupg/gpg.conf 131 | # Add line: 132 | default-key E870EE00 133 | ``` 134 | 135 | ## Optional: Fix for Git UIs 136 | 137 | If you use a UI such as Git Tower or Github Desktop, you may need to configure git to point to the specific gpg executable: 138 | ```sh 139 | git config --global gpg.program $(which gpg) 140 | ``` 141 | 142 | ## Optional: Disable TTY 143 | If you have problems with making autosigned commits from IDE or other software add no-tty config 144 | ```sh 145 | $ $EDITOR ~/.gnupg/gpg.conf 146 | # Add line: 147 | no-tty 148 | ``` 149 | 150 | ## Optional: Setting up TTY 151 | Depending on your personal setup, you might need to define the tty for gpg 152 | whenever your passphrase is prompted. Otherwise, you might encounter an `Inappropriate 153 | ioctl for device` error. 154 | ```sh 155 | $ $EDITOR ~/.profile # or other file that is sourced every time 156 | # Paste these lines 157 | GPG_TTY=$(tty) 158 | export GPG_TTY 159 | ``` 160 | 161 | ## Optional: In case you're prompted to enter the password every time 162 | 163 | > Some people found that this works out of the box w/o following these steps. 164 | 165 | ### Method 1 - gpg-agent + pinentry-mac 166 | 167 | Install pinentry-mac: 168 | 169 | ```sh 170 | $ brew install pinentry-mac 171 | ``` 172 | 173 | Set up the agent: 174 | 175 | ```sh 176 | $ $EDITOR ~/.gnupg/gpg-agent.conf 177 | # Paste this line for Apple silicon: 178 | pinentry-program /opt/homebrew/bin/pinentry-mac 179 | # For Intel-based Macs, paste this line instead: 180 | pinentry-program /usr/local/bin/pinentry-mac 181 | ``` 182 | 183 | Now `git commit -S`, it will ask your password and you can save it to macOS 184 | keychain. 185 | 186 | ![pinentry](img/pinentry.png) 187 | 188 | ### Method 2 - GPG Suite 189 | 190 | Some people find that pinentry installed with brew does not allow the password to be saved to macOS's keychain. 191 | 192 | If you do not see "Save in Keychain" after following Method 1, first uninstall the version of pinentry-mac installed with brew: 193 | 194 | ```sh 195 | $ brew uninstall pinentry-mac 196 | ``` 197 | 198 | Now install the GPG Suite versions, available from [gpgtools.org](https://gpgtools.org/#gpgsuite), or from brew by running: 199 | 200 | ```sh 201 | $ brew install --cask gpg-suite 202 | ``` 203 | 204 | Once installed, open Spotlight and search for "GPG Suite", or open system preferences and select "GPG Suite" 205 | 206 | Select the Default Key if it is not already selected, and ensure "Store in OS X Keychain" is checked: 207 | 208 | ![gpg preferences](img/gpg-preferences.png) 209 | 210 | The `gpg-agent.conf` is different from Method 1: 211 | 212 | Set up the agent: 213 | 214 | ```sh 215 | $ $EDITOR ~/.gnupg/gpg-agent.conf 216 | # GPG Suite should pre-populate with something similar to the following: 217 | default-cache-ttl 600 218 | max-cache-ttl 7200 219 | ``` 220 | 221 | 222 | ### Testing without a Git Commit 223 | 224 | While a full end-to-end test by committing something to git will confirm for sure if things are working, a quick thing you can check is: 225 | 226 | ``` 227 | echo "test" | gpg --clearsign 228 | ``` 229 | 230 | This will output something like this if everything goes well: 231 | 232 | ``` 233 | $ echo "test" | gpg --clearsign 234 | gpg: WARNING: server 'gpg-agent' is older than us (2.2.40 < 2.4.0) 235 | gpg: Note: Outdated servers may lack important security fixes. 236 | gpg: Note: Use the command "gpgconf --kill all" to restart them. 237 | gpg: using "9DAC53FB18AB8C5DF0E2AA5B330CB62AE334C5E2" as default secret key for signing 238 | gpg: problem with fast path key listing: IPC parameter error - ignored 239 | -----BEGIN PGP SIGNED MESSAGE----- 240 | Hash: SHA256 241 | 242 | test 243 | -----BEGIN PGP SIGNATURE----- 244 | 245 | iQEzBAEBCAAdFiEEmpcZZDDypeoq25Aer4d9fatgnzQFAmPmbXEACgkQr4d9fatg 246 | nzQ/RAf9Elo6RUbb1xWdyPVHqS6Eq67eWmbJ62WriI+2ldMjj8lZp4XtcZ0KzXnO 247 | 0U4moVhZyQqBQ1syDC8UNXsTI7pzbRuZ1dzs5tjo+6UuqGfzpgurvw//3L/LxujJ 248 | 5asFq//sDNLCHFUAFDbmuWqfcMqpp/KqtaJr8EuCSb/3HSy4J8lMNGyQ4wmpQs5U 249 | Qr5IPLq07NQrOQC3d4vXOmWqY9EZYeSbf0QWCMiErHLxm/jQY+TP88lNre99GmED 250 | 4mAD2+I5wd33MizbjfTSH/RAeT5MdLwiBzc6kVjxu4BWusPmdUgLs7vPuP3qeqMQ 251 | q9VnL6mMsaFm0rKnID/MoOPtaghgSA== 252 | =1T8z 253 | -----END PGP SIGNATURE----- 254 | ``` 255 | --------------------------------------------------------------------------------