Setup GPG + SSH keys for multiple git profiles

Having multiple git accounts, either for personal use and/or having one or more for work, then is really handy to setup GPG keys to singing commits and SSH keys to use git + ssh.

GPG

GnupPG (GNU Privacy Guard) is a public key cryptography implementation and allows it to encrypt, sign data and communications.
In the software development world commonly GPG keys are used to sign (verify) our git commits. And why do we want to sign our commits ?
The answer is pretty straight forward. Our emails and names are not private and can be easily to know to everybody and I can use:
git config user.name and git config user.email with any name and email and commits with those values and from the point of view of git, this is working as intended. Being able to impersonate other committers does not introduce vulnerability because when we want to do git push GitHub or GitLab would require us to authenticate with the credentials before we could be able to do that. But unsigned commits does not guarantee the following:
– The author is really the person who says in the commit.
– The code change is really what the author wrote without been manipulated.

Signing our commits give us the ability to prove we were the author of our code changes. Also no one can modify our commits in the future or even the metadata such as the time we claimed it was made at.

First thing, we need to install GPG.

Installing GPG

Install the latest version.
– On windows, download the Gpg4win from gnupg website.
– On Mac use Home brew: brew install gpg. Also install pin entry-mac with brew install pinentry-mac.
Then restart GPG agent: gpgconf --kill gpg-agent.
This file should be present: ~/.gnupg/gpg-agent.conf with something like this as content: pinentry-program /Users/unixb0y/.brew/homebrew/bin/pinentry
The path should be where homebrew installed pinentry, the path may differ if you have M1 Macs or intel Macs.
– Add GPG_TTY into your environment variables by adding this line export GPG_TTY=$(tty)into ~/.zprofile or ~/.zshrc.
– Most linux distros come with GPG pre-installed, if not you can find it from their official repositories.

Generate a GPG Key pair

Run the following command: gpg --full-key-gen
– Select option 4 (RSA)
– Keysize 4096
– 0 (key does not expire)
Then answer a few questions, Your real name and email address.
After this you are going to be asked to type a passphrase which is used to encrypt your secret key. This is very important and you should fill the passphrase and not leave it empty. Otherwise hackers could steal your secret and then they’ll be able to signing commits pretending to be you.

To verify the keys you have created, run: gpg --list-secret-keys --keyid-format LONG

gpg –list-keys –keyid-format LONG

gpg --list-keys --keyid-format LONG
/Users/ffgm/.gnupg/pubring.kbx
------------------------------
pub   rsa4096/F2B0CF302345F4239 2022-02-09 [SC]
      4A0BD48948DBF4654F8E149CE1B9FF30654F4389
uid                 [ultimate] Your Name <email@adress.com>
sub   rsa4096/F2B0CF302345F4239 2022-02-09 [E]

To test gpg is working you can run echo "hello test" | gpg --clearsign to signing hello test.

Configure Git to sign your commits

your ~/.gitconfig should look like this:

[commit]
 	gpgsign = true
 
[user]
	useConfigOnly = true

[includeIf "gitdir:/Users/ffgm/personal/"]
	path = ~/.gitconfig.personal
    
[includeIf "gitdir:/Users/ffgm/workspace/"]
	path = ~/.gitconfig.workspace

gpgsign enabled enforce the commit signing on every commit. includeif is for separate our configuration depending on what folder are we working on. If I’m in ~/ffgm/personal then the personal configuration is going to be used. Meaning git is going to use the personal gpg signing key.
useConfigOnly prevents git from guessing name and email and forces it to read it from the configuration files. If the email is missing, git will complain when you try to do a commit or push.

./gitconfig.personal

[user]
    email = your.personal@email.here
    name = Your Name
    signingKey = <PERSONAL GPG SIGNING KEY ID>

[url "git@gitlab.com-personal"]
	insteadOf = git@gitlab.com

./gitconfig.workspace

[user]
    signinkey = <WORK SIGN IN KEY>
    name = Your Name
    email = work@email.com
    
[url "git@gitlab.com-workspace"]
	insteadOf = git@gitlab.com

Make sure to upload the gpg key into gitlab, GitHub or whatever is your git provider.
gpg --armor --export YOUR-KEY it will give you your public key to copy and pasted in your git provider.

SSH Configuration

To generate ssh keys run the following command: `ssh-keygen -t ed25519 -C “your-email@example.com”.
You can use other algorithms but ed25519 is the recommended one.

./ssh/config

Host gitlab.com-personal
    PreferredAuthentications publickey
    HostName gitlab.com
    User personal-gitlab-user
    IdentityFile ~/.ssh/personal_id_ed25519

Host gitlab.com-workspace
    PreferredAuthentications publickey
    HostName gitlab.com
    User work-gitlab-user
    IdentityFile ~/.ssh/workspace_id_ed25519

Host *
    AddKeysToAgent yes
    IdentitiesOnly yes
	PreferredAuthentications publickey
	Compression yes
	UseKeychain yes

Is important to not change the order of the configuration.

Also you need to upload the ssh key into your preferred git provider.

Once you have set up gpg and ssh you can see your commits with the verified label:

screenshot 2023 03 15 at 165133

Author

Fernando Garcia