Master key will be used only for certification - signing certfiicates for subkeys. Sign, Encrypt, Authenticate will be delegated to subkey/s.
Run gpg --expert --full-generate-key
- Choose RSA (set your own capabilities)
- Disable sign - type
S
- Disable encrypt - type
E
- Quit & continue - type
Q
- Input 4096 as desired size
- Setup expiration. I'm setting 0 - never.
- Construct the user id - input full name and email. leav comment empty.
- Choose your passphrase
We'll generate one subkey for sign, encrypt, authenticate - feel free to make separate if you wish
Run gpg --expert --edit-key <email>
When in the gpg run addkey
- Choose RSA (set your own capabilities)
- Add authenticate - type
A
- Quit & continue - type
Q
- Input 4096 as desired size
- Setup expiration. I'm setting 0 - its not good practice, but its me :)
- Now input the passhphrase of the master
- Save and exit - type
save
The below will instruct the agent deamon to start with ssh support and configures the pinentry program for the TTY input. We also set default cache to 1 day
enable-ssh-support
pinentry-program /usr/local/bin/pinentry-curses
default-cache-ttl 86400
max-cache-ttl 86400
How to get pinentry-curses to start on the correct tty?
The below is configuring SSH to use gpg-agent instead of ssh-agent and instructs pinentry-curses to start on the correct tty.
unset SSH_AGENT_PID
if [ "${gnupg_SSH_AUTH_SOCK_by:-0}" -ne $$ ]; then
export SSH_AUTH_SOCK="$(gpgconf --list-dirs agent-ssh-socket)"
fi
export GPG_TTY=$(tty)
gpg-connect-agent updatestartuptty /bye >/dev/null
In our case we have one subkey, but if you have separate for auth pick it
Get the subkey keygrip
To find the keygrip id run gpg --list-keys --with-keygrip
Add the keygrip to the list with approved keys
echo <keygrip id> >> ~/.gnupg/sshcontrol
Verify that this key now is in the ssh identities list with ssh -L
killall ssh-agent gpg-agent
unset GPG_AGENT_INFO SSH_AGENT_PID SSH_AUTH_SOCK
eval $(gpg-agent --daemon --enable-ssh-support)
Now we need to export to ssh format our public key (ssh key) and add it to github as SSH authentication key.
Run gpg --export-ssh-key <key id/email>
Now get the result and paste it in github as authentication key.
Test that the key is working with your github account
ssh -T [email protected]
Get the key id of your subkey gpg --list-secret-keys --keyid-format long
- the id is after the rsa4096/
Now export this key in ASCII armor gpg --armor --export
Add it ass new GPG key to github.
Configure git to use this key to sign commits
git config --global user.signingkey <key id>!
Note that the ! in the end is important to force always to use this key.
Optionally enable git to always sign commits git config --global commit.gpgsign true
Now to test sign some commit git commit -a -S -m 'Signed commit'
Check the commit signature git log --show-signature -1
You should see good signature confirmation.
Also note that in order to display verified badge in github the GPG key email & the commit email should be the same and the email address to be verified.
To stay safe if things go wrong we'll operate with offline master key (not present).
Export the secret master
gpg -a --export-secret-keys > master-secret-key.gpg
Export secret subkeys
gpg -a --export-secret-subkeys > sub-secret-keys.gpg
Delete key and subkeys
gpg --delete-secret-key <id>
Import the subkeys
gpg --import sub-secret-keys.gpg
Verify that keys are not with offline master
gpg -K
You should see sec#
the # indicates that this is offline.
In case you have new machine and you want to use your backed up keys
gpg --import master-secret-key.gpg
gpg --import sub-secret-keys.gpg
Verify keys are there by gpg -K
You will notice that it says [undefined] for the key trust
To give trust to you imported keys
gpg --edit-key <id/email>
type trust
choose ultimate trust
type save