This is a step-by-step guide on how to create a GPG key on keybase.io, adding it to a local GPG setup and use it with Git and Gitlab.
MacOS
: Usehomebrew
Linux
: Useapt-get
,apk
, etc- Windows: Get a better life, replace the entire OS with MacOS or Linux
Use the appropriate command for your OS...
- Install GPG CLI:
$ brew install gpg
- Install Keybase:
Install from the website https://prerelease.keybase.io/
- You should now have both the keycloak CLI and the Keybase desktop app (
/Applications/Keybase
). Open the Keybase app, create an account and sign in.
- Generate new SSH keys:
$ ssh-keygen -o -t rsa -b 4096 -C "[email protected]"
- Copy your public SSH key to your clipboard:
cat ~/.ssh/id_rsa.pub | pbcopy
- Add the key to repos
- https://docs.gitlab.com/ee/ssh/
- https://docs.github.com/en/authentication/connecting-to-github-with-ssh/generating-a-new-ssh-key-and-adding-it-to-the-ssh-agent
- Test that this worked by cloning a repo using the
git://
protocol
This should succeed if you are a member of the repo and that you can clone the repo read/write permissions.
- Generate a new PGP key and write it to your local secret keychain:
$ keybase pgp gen --multi
# Enter your real name, which will be publicly visible in your new key: Patrick Stadler
# Enter a public email address for your key: [email protected]
# Enter another email address (or <enter> when done):
# Push an encrypted copy of your new secret key to the Keybase.io server? [Y/n] Y
# βΆ INFO PGP User ID: Patrick Stadler <[email protected]> [primary]
# βΆ INFO Generating primary key (4096 bits)
# βΆ INFO Generating encryption subkey (4096 bits)
# βΆ INFO Generated new PGP key:
# βΆ INFO user: Patrick Stadler <[email protected]>
# βΆ INFO 4096-bit RSA key, ID CB86A866E870EE00, created 2016-04-06
# βΆ INFO Exported new key to the local GPG keychain
You will be prompted to set a passphrase. Create a strong, 31-character password using your Keychain Access app (see reference image above).
Enter it twice to confirm. Since you will likely need it again, store this password somewhere secure, like as a Secure Note in Keychain Access, or in a password manager like LastPass.
Keybase Commands: https://book.keybase.io/docs/cli#basics Explanation: https://davidwinter.dev/managing-gpg-with-keybase/ NOTE: Make sure to set export GPG_TTY=$(tty) before starting
$ cat ~/.zshenv
export GPG_TTY=$(tty)
if [ -f $HOME/.cargo/env ]; then
. "$HOME/.cargo/env"
fi
- Login and verify user (Note that if the desktop version is available you are all logged in)
$ keybase login
$ keybase whoami
marcellodesales
$ keybase status
Username: marcellodesales
Logged in: yes
Device:
name: Mac Device - Work **** M1 MAC
ID: 92b8a65*****01318
status: active
...
...
- Look for the key required
$ keybase pgp list
Keybase Key ID: 0101cd33c5162998afc99ae6ec76f1bea8709b1046dc036a23ce356a4e47947588ae0a
PGP Fingerprint: 3c7a2b7ba9e2c86d5f0bfc26dc4e536ee3a84b25
PGP Identities:
Marcello DeSales <[email protected]>
Marcello DeSales <[email protected]>
- Inspect the public key
- That can be used to past the keys at
$GITHUB_HOST/settings/keys
GPG keys section.
- That can be used to past the keys at
$ keybase pgp export -q 3c7a2b7ba9e2c86d5f0bfc26dc4e536ee3a84b25
-----BEGIN PGP PUBLIC KEY BLOCK-----
Comment: https://keybase.io/download
Version: Keybase Go 5.9.0 (darwin)
xsFNBGHYp1cBEACZ7CcPxd7cqKzgn3eYgSra1HUOqRbVM9H8fNNIl5COat/NxZb5
r3WJNHWEyyHkR2CuZuxxp7+QglmSA/iLWOGwXvbhuLMrDgObUlREHAiqs3eBaS/u
...
...
- Export the public
$ keybase pgp export -q 3c7a2b7ba9e2c86d5f0bfc26dc4e536ee3a84b25 | gpg --import
gpg: key DC4E536EE3A84B25: public key "Marcello DeSales <[email protected]>" imported
gpg: Total number processed: 1
gpg: imported: 1
NOTE: You must have the env
GPG_TTY=$(tty)
so that the prompt shows up in the terminal to import the private key Sometimes the prompt will not show if this is not set
$ keybase pgp export -q 3c7a2b7ba9e2c86d5f0bfc26dc4e536ee3a84b25 --secret | gpg --allow-secret-key-import --import
gpg: key DC4E536EE3A84B25: "Marcello DeSales <[email protected]>" not changed
gpg: key DC4E536EE3A84B25: secret key imported
gpg: Total number processed: 1
gpg: unchanged: 1
gpg: secret keys read: 1
gpg: secret keys imported: 1
$ gpg --list-secret-key --keyid-form LONG
/Users/marcellodesales/.gnupg/pubring.kbx
-----------------------------------------
sec rsa4096/DC*****25 2022-01-07 [SC] [expires: 2038-01-03]
3C7A2B7B***********6EE3A84B25
uid [ unknown] Marcello DeSales <[email protected]>
uid [ unknown] Marcello DeSales <[email protected]>
ssb rsa4096/E73E*******FF 2022-01-07 [E] [expires: 2038-01-03]
- keybase
keybase pgp export -q DC4E******25 | pbcopy
- gpg
$ gpg --armor --export DC*****B25
-----BEGIN PGP PUBLIC KEY BLOCK-----
mQINBGHYp1cBEACZ7CcPxd7cqKzgn3eYgSra1HUOqRbVM9H8fNNIl5COat/NxZb5
r3WJNHWEyyHkR2CuZuxxp7+QglmSA/iLWOGwXvbhuLMrDgObUlREHAiqs3eBaS/u
...
...
9trpzNMK2HHhLExRbsVf8ZSg5h3s5Pq+mvnimBvfNuHhqgKfIFERgH/YDl4LhHkB
vBXF3x3sBpWVJxutordywK4=
=k2Ne
-----END PGP PUBLIC KEY BLOCK-----
- Obtain your signing key via the GPG CLI:
$ gpg --list-secret-keys --keyid-format LONG
/Users/jplew/.gnupg/pubring.kbx
-------------------------------
sec rsa4096/C8AB98F11Y123456 2018-06-02 [SC] [expires: 2034-05-29]
B21DBAB6AA037F5641504A8CC2DB56E29C562080
uid [ unknown] JP Lew <[email protected]>
ssb rsa4096/ZZ1Z1234556FAPPO 2018-06-02 [E] [expires: 2034-05-29]
Your signingkey
is the 16-character string on the sec
line, following rsa4096/
.
gpg --list-secret-keys --keyid-format LONG | grep sec | awk '{ print $2 }' | awk -F"/" '{ print $2 }'
DC4*****25
- Add your signing key and user info to your global Git config file. To do this this, you can either:
$ git config --global user.name "Marcello DeSales"
$ git config --global user.email [email protected]
$ git config --global user.signingkey DC4*****25
$ git config --global commit.gpgsign true
The final product should look like this:
- Default config is with open-source email address
- Work email address stays in separate config
cat ~/.gitconfig
- It can also have its own section for the signing
[user]
name = Marcello DeSales
email = [email protected]
signingkey = DC4E******B25
[commit]
gpgsign = true
[tag]
gpgsign = true
[includeIf "gitdir:~/dev/gitlab.com/supercash/"]
path = ~/.gitconfig-super.cash
[color]
ui = true
NOTE: YOU MUST SPECIFY THE
includeIf
ending with/
- Config for work address
cat ~/.gitconfig-super.cash
[user]
email = [email protected]
In order to verify, just cd to the dir of your projects
βοΈ [email protected] π [email protected]
βΈοΈ [email protected] π [email protected] π‘ [email protected] π½ [email protected] βοΈ [email protected] π [email protected]
π€ AWS_PS1_PROFILE ποΈ π sa-east-1
π 1.21.2-eks-0389ca3 π arn:aws:eks:sa-east-1:806101772216:cluster/eks-ppd-prd-super-cash π± default
~/dev/github.com/marcellodesales/Systems-Design on ξ master! π
01-07-2022 β14:18:19
$ git config user.email
[email protected]
βοΈ [email protected] π [email protected]
βΈοΈ [email protected] π [email protected] π‘ [email protected] π½ [email protected] βοΈ [email protected] π³ [email protected] π [email protected]
π€ AWS_PS1_PROFILE ποΈ π sa-east-1
π 1.21.2-eks-0389ca3 π arn:aws:eks:sa-east-1:806101772216:cluster/eks-ppd-prd-super-cash π± default
~/dev/gitlab.com/supercash/apps-web/maceio-shopping-tickets-web on ξ develop! π
01-07-2022 β14:17:43
$ git config user.email
[email protected]
REF: https://docs.gitlab.com/ee/user/project/repository/gpg_signed_commits
- Go to the key settings of your repo server
- Copy your public key to your clipboard by running:
$ keybase pgp export -q C8A*****456 | pbcopy
Make sure you use your actual signing key.
-
Paste your key and save.
-
Test that this worked by signing a git commit and submitting a merge request.
$ cd myrepo
$ git touch newfile.txt
$ git commit -m "make a GPG signed commit"
$ git --no-pager show --show-signature
commit 0d9c2366a58c985b3ce31c32ad092ecf0a0ba378 (HEAD -> feature/pipeline-with-deployment-cloudfront)
gpg: Signature made Fri Jan 7 13:16:19 2022 PST
The commit should show the signed information with gpg:
on it...
- If you are allowed to create a merge request, it worked.
- commands like
git log --show-signature
will show the problem
$ git --no-pager show --show-signature
commit 0d9c2366a58c985b3ce31c32ad092ecf0a0ba378 (HEAD -> feature/pipeline-with-deployment-cloudfront)
gpg: Signature made Fri Jan 7 13:16:19 2022 PST
gpg: using RSA key 3C7A****B25
gpg: WARNING: This key is not certified with a trusted signature!
gpg: There is no indication that the signature belongs to the owner.
Author: Marcello DeSales <[email protected]>
Date: Fri Jan 7 13:16:19 2022 -0800
:memo: README: update title to be shorter
REF: https://serverfault.com/questions/569911/how-to-verify-an-imported-gpg-key/569923#569923
- List the key ID
$ gpg --list-secret-keys --keyid-format LONG | grep sec | awk '{ print $2 }' | awk -F"/" '{ print $2 }'
DC4*****B25
- Edit the key
$ gpg --edit-key DC4****B25
gpg (GnuPG) 2.3.4; Copyright (C) 2021 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/DC4****25
created: 2022-01-07 expires: 2038-01-03 usage: SC
trust: unknown validity: unknown
ssb rsa4096/E73******7FF
created: 2022-01-07 expires: 2038-01-03 usage: E
[ unknown] (1). Marcello DeSales <[email protected]>
[ unknown] (2) Marcello DeSales <[email protected]>
- On the prompt, type trust
gpg> trust
sec rsa4096/DC4*****25
created: 2022-01-07 expires: 2038-01-03 usage: SC
trust: unknown validity: unknown
ssb rsa4096/E73EBAAEC18957FF
created: 2022-01-07 expires: 2038-01-03 usage: E
[ unknown] (1). Marcello DeSales <[email protected]>
[ unknown] (2) Marcello DeSales <[email protected]>
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/DC4****25
created: 2022-01-07 expires: 2038-01-03 usage: SC
trust: ultimate validity: unknown
ssb rsa4096/E73****7FF
created: 2022-01-07 expires: 2038-01-03 usage: E
[ unknown] (1). Marcello DeSales <[email protected]>
[ unknown] (2) Marcello DeSales <[email protected]>
Please note that the shown key validity is not necessarily correct
unless you restart the program.
gpg> q
- Set the commit prompt to ask for the passthrase of signature once it finishes the commit
export GPG_TTY=$(tty)`
- Make a new commit... It will ask for the passphrase of the key
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
β Please enter the passphrase to unlock the OpenPGP secret key: β
β "Marcello DeSales <[email protected]>" β
β 4096-bit RSA key, ID DC*****25, β
β created 2022-01-07. β
β β
β β
β Passphrase: _________________________________________________ β
β β
β <OK> <Cancel> β
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
- Upon entering the passphrase, the commit works... Now you can verify it is signed
# https://stackoverflow.com/questions/3357280/print-commit-message-of-a-given-commit-in-git/54886099#54886099
$ git --no-pager show --show-signature -s --format=%s
gpg: Signature made Sun Jul 3 19:08:06 2022 PDT
gpg: using RSA key 33F17EFF7BD0A66A8C533A41A0CDC02D297930BF
gpg: Good signature from "Marcello DeSales <[email protected]>" [ultimate]
gpg: aka "Marcello DeSales <[email protected]>" [ultimate]
:tada: :memo: Add readme initial for the project
$ git --no-pager show --show-signature
commit 0d9c2366a58c985b3ce31c32ad092ecf0a0ba378 (HEAD -> feature/pipeline-with-deployment-cloudfront)
gpg: Signature made Fri Jan 7 13:16:19 2022 PST
gpg: using RSA key 3C7A2B7BA9*******84B25
gpg: Good signature from "Marcello DeSales <[email protected]>" [ultimate]
gpg: aka "Marcello DeSales <[email protected]>" [ultimate]
Author: Marcello DeSales <[email protected]>
Date: Fri Jan 7 13:16:19 2022 -0800
:memo: README: update title to be shorter
diff --git a/README.md b/README.md
index 28748c1..652b6be 100644
--- a/README.md
+++ b/README.md
Install the GPG Suite, available from gpgtools.org, or from brew by running:
$ brew install --cask gpg-suite
Once installed, open Spotlight and search for "GPGPreferences", or open system preferences and select "GPGPreferences"
Select the Default Key if it is not already selected, and ensure "Store in OS X Keychain" is checked (see reference image above):
The gpg-agent.conf
is different from Method 1:
Set up the agent:
$ $EDITOR ~/.gnupg/gpg-agent.conf
# GPG Suite should pre-populate with something similar to the following:
default-cache-ttl 600
max-cache-ttl 7200
- You can verify all your accounts from the Keybase UI
- Still can't on Gitlab https://gitlab.com/gitlab-org/gitlab/-/issues/28209#note_804775223
Steps described at https://serverfault.com/questions/86048/how-to-backup-gpg/1040984#1040984
When installing the public/private keys in a new computer. Make sure to back them up and store them in a secure location.
- List the existing keys before transferring to another computer
- Export all what needs:
- public key
- private key
- sub private keys
- ownership
- Verify the keys
Here's the current list of keys
$ gpg -k
/Users/marcellodesales/.gnupg/pubring.kbx
-----------------------------------------
pub rsa4096 2022-01-07 [SC] [expires: 2038-01-03]
3C7A2B7BA9E2C86D5F0BFC26DC4E536EE3A84B25
uid [ultimate] Marcello DeSales <[email protected]>
uid [ultimate] Marcello DeSales <[email protected]>
sub rsa4096 2022-01-07 [E] [expires: 2038-01-03]
- Choose any of the identifications of the key such as the name or email
$ gpg --export --armor [email protected] > [email protected]
$ cat ~/[email protected] | head -5 && echo "...\n...\n" && cat ~/[email protected] | tail -5
-----BEGIN PGP PUBLIC KEY BLOCK-----
mQINBGHYp1cBEACZ7CcPxd7cqKzgn3eYgSra1HUOqRbVM9H8fNNIl5COat/NxZb5
r3WJNHWEyyHkR2CuZuxxp7+QglmSA/iLWOGwXvbhuLMrDgObUlREHAiqs3eBaS/u
ZMLnX8zMlfi0YtAuiQTkayDNCYNTev138E+JGo58eCUEMUe+USTzmz8j9sHojuCD
...
...
fJREULTai3kRHgHSNLrd8I04beMeGYmJwOcXe3fIO4hJt7PP6X0F3Q4B+i/zaP+4
9trpzNMK2HHhLExRbsVf8ZSg5h3s5Pq+mvnimBvfNuHhqgKfIFERgH/YDl4LhHkB
vBXF3x3sBpWVJxutordywK4=
=k2Ne
-----END PGP PUBLIC KEY BLOCK-----
- Choose any of the identifications of the key such as the name or email
$ gpg --export-secret-keys --armor [email protected] > [email protected]
$ cat ~/[email protected] | head -5 && echo "...\n...\n" && cat ~/[email protected] | tail -5
-----BEGIN PGP PRIVATE KEY BLOCK-----
lQdGBGHYp1cBEACZ7CcPxd7cqKzgn3eYgSra1HUOqRbVM9H8fNNIl5COat/NxZb5
r3WJNHWEyyHkR2CuZuxxp7+QglmSA/iLWOGwXvbhuLMrDgObUlREHAiqs3eBaS/u
ZMLnX8zMlfi0YtAuiQTkayDNCYNTev138E+JGo58eCUEMUe+USTzmz8j9sHojuCD
...
...
3fCNOG3jHhmJicDnF3t3yDuISbezz+l9Bd0OAfov82j/uPba6czTCthx4SxMUW7F
X/GUoOYd7OT6vpr54pgb3zbh4aoCnyBREYB/2A5eC4R5AbwVxd8d7AaVlScbraK3
csCu
=d+0l
-----END PGP PRIVATE KEY BLOCK-----
$ gpg --export-secret-subkeys --armor [email protected] > [email protected]_priv.asc
$ cat ~/[email protected]_priv.asc | head -5 && echo "...\n...\n" && cat ~/[email protected]_priv.asc | tail -5
-----BEGIN PGP PRIVATE KEY BLOCK-----
lQIVBGHYp1cBEACZ7CcPxd7cqKzgn3eYgSra1HUOqRbVM9H8fNNIl5COat/NxZb5
r3WJNHWEyyHkR2CuZuxxp7+QglmSA/iLWOGwXvbhuLMrDgObUlREHAiqs3eBaS/u
ZMLnX8zMlfi0YtAuiQTkayDNCYNTev138E+JGo58eCUEMUe+USTzmz8j9sHojuCD
...
...
MnyURFC02ot5ER4B0jS63fCNOG3jHhmJicDnF3t3yDuISbezz+l9Bd0OAfov82j/
uPba6czTCthx4SxMUW7FX/GUoOYd7OT6vpr54pgb3zbh4aoCnyBREYB/2A5eC4R5
AbwVxd8d7AaVlScbraK3csCu
=4eYm
-----END PGP PRIVATE KEY BLOCK-----
$ gpg --export-ownertrust > ownertrust.txt
$ cat ownertrust.txt
# List of assigned trustvalues, created Fri May 24 18:52:42 2024 PDT
# (Use "gpg --import-ownertrust" to restore them)
3C7A2B7BA9E2C86D5F0BFC26DC4E536EE3A84B25:6:
- Start from the public key
$ gpg --import [email protected]
gpg: directory '/Users/marcellodesales/.gnupg' created
gpg: /Users/marcellodesales/.gnupg/trustdb.gpg: trustdb created
gpg: key DC4E536EE3A84B25: public key "Marcello DeSales <[email protected]>" imported
gpg: Total number processed: 1
gpg: imported: 1
ATTENTION: If you try to add the private key, you will get errors.
- Add the ownership trust first, then, add the private key... Skip this step
~ β 18:54:47
$ gpg --import [email protected]
gpg: key DC4E536EE3A84B25: "Marcello DeSales <[email protected]>" not changed
gpg: key DC4E536EE3A84B25/DC4E536EE3A84B25: error sending to agent: Bad passphrase
gpg: error building skey array: Bad passphrase
gpg: error reading '[email protected]': Bad passphrase
gpg: import from '[email protected]' failed: Bad passphrase
gpg: Total number processed: 0
gpg: unchanged: 1
gpg: secret keys read: 1
- Add the ownertrust
$ gpg --import-ownertrust ownertrust.txt
gpg: inserting ownertrust of 6
- Then, add the sub private keys first
$ gpg --import [email protected]_priv.asc
gpg: key DC4E536EE3A84B25: "Marcello DeSales <[email protected]>" not changed
gpg: To migrate 'secring.gpg', with each smartcard, run: gpg --card-status
gpg: key DC4E536EE3A84B25: secret key imported
gpg: Total number processed: 1
gpg: unchanged: 1
gpg: secret keys read: 1
gpg: secret keys imported: 1
- Attempting to add the private keys
$ gpg --import [email protected]
gpg: key DC4E536EE3A84B25: "Marcello DeSales <[email protected]>" not changed
gpg: key DC4E536EE3A84B25: secret key imported
gpg: Total number processed: 1
gpg: unchanged: 1
gpg: secret keys read: 1
gpg: secret keys imported: 1
gpg: secret keys unchanged: 1
- Show the keys
$ gpg --list-secret-keys --keyid-format LONG
gpg: checking the trustdb
gpg: marginals needed: 3 completes needed: 1 trust model: pgp
gpg: depth: 0 valid: 1 signed: 0 trust: 0-, 0q, 0n, 0m, 0f, 1u
gpg: next trustdb check due at 2038-01-03
[keyboxd]
---------
sec rsa4096/DC4E536EE3A84B25 2022-01-07 [SC] [expires: 2038-01-03]
3C7A2B7BA9E2C86D5F0BFC26DC4E536EE3A84B25
uid [ultimate] Marcello DeSales <[email protected]>
uid [ultimate] Marcello DeSales <[email protected]>
ssb rsa4096/E73EBAAEC18957FF 2022-01-07 [E] [expires: 2038-01-03]