Skip to content

gpg

notes

prerequisites
  • install git, gnupg, and ykman

    apt install -y git gnupg ykman
    
    pacman -S --noconfirm git gnupg ykman
    
  • install git, gpg4win, and ykman

    winget install -eh --id Git.Git
    winget install -eh --id GnuPG.Gpg4win
    winget install -eh --id Yubico.YubikeyManager
    
  • add ykman as an execution alias

    nvim $PROFILE
    
    $PROFILE
    ...
    Set-Alias ykman "C:\Program Files\Yubico\YubiKey Manager\ykman.exe"
    ...
    
  • disable git's internal gpg and ssh services

    as administrator
    Move-Item -Path "C:\Program Files\Git\usr\bin\gpg.exe" -Destination "C:\Program Files\Git\usr\bin\gpg_disabled.exe"
    Move-Item -Path "C:\Program Files\Git\usr\bin\ssh.exe" -Destination "C:\Program Files\Git\usr\bin\ssh_disabled.exe"
    
    • this may have to be repeated each time git updates
variables
variable description example
NAME first and last names John Doe
FIRST_NAME first name John
LAST_NAME last name Doe
EMAIL github private relay email address 12345678+username@users.noreply.github.com
KEY gpg key id 89ABCDEF
AUTH_KEY gpg authentication key id 89ABCDEF
AUTH_KEYGRIP gpg authentication keygrip 0123456789ABCDEF0123456789ABCDEF01234567
PASSPHRASE gpg passphrase FakePassword123
ADMIN_PIN yubikey gpg module administrator pin default is 12345678
PIN yubikey gpg module pin default is 123456
URL url of raw github gist of pub gpg key https://gist.githubusercontent.com/username/.../raw/.../pub.gpg
resources

brief

  • this opinionated guide shows how to create a gpg key with subkeys, copy relevant gpg key data to any number of yubikeys, enabling usage of those yubikeys for signing (via gpg) and authentication (via gpg/ssh)
  • I hope to amend this guide in the future to avoid the mirroring of yubikeys

gpg setup

creating gpg key

cd ~/Downloads
gpg --full-generate-key --expert
11 | s | q | 1 | ENTER | y | $NAME | $EMAIL | ENTER | o | $PASSPHRASE | "OK" | $PASSPHRASE | "OK"
gpg --list-keys --keyid-format short # (1)!
gpg --edit-key --expert $KEY
  1. find KEY now
addkey | 10 | 1 | 3y | y | y | $PASSPHRASE | "OK"
addkey | 12 | 1 | 3y | y | y | $PASSPHRASE | "OK"
addkey | 11 | s | a | q | 1 | 3y | y | y | $PASSPHRASE | "OK" | save
gpg --export --armor $KEY | clip # (1)!
  1. pub gpg key is in the clipboard

make sure you've...

  • added the pub gpg key to your github user settings under gpg keys
  • added the pub gpg key to a github gist for public availability

backing up gpg key

1
2
3
gpg --export --armor $KEY > $KEY.pub.gpg
gpg --export-ownertrust > $KEY.trust.txt
gpg --output $KEY.revoke.asc --gen-revoke $KEY
y | 0 | ENTER | y | $PASSPHRASE | "OK"
gpg --export-secret-keys --armor $KEY > $KEY.priv.gpg
$PASSPHRASE | "OK"
gpg --export-secret-subkeys --armor $KEY > $KEY.priv.sub.gpg
$PASSPHRASE | "OK"
6
7
8
9
tar -czvf "$(date '+%F').pub.gpg.tar.gz" *pub.gpg *trust.txt
tar -czvf "$(date '+%F').priv.gpg.tar.gz" *revoke.asc *priv.gpg
tar -czvf "$(date '+%F').priv.sub.gpg.tar.gz" *priv.sub.gpg
rm -rf *tar.gz *revoke.asc *pub.gpg *priv.gpg *trust.txt
6
7
8
9
Get-Date -UFormat "%F" | ForEach-Object {7z -t7z a "$_.pub.gpg.7z" *pub.gpg *trust.txt} > $null
Get-Date -UFormat "%F" | ForEach-Object {7z -t7z a "$_.priv.gpg.7z" *revoke.asc *priv.gpg} > $null
Get-Date -UFormat "%F" | ForEach-Object {7z -t7z a "$_.priv.sub.gpg.7z" *priv.sub.gpg} > $null
del *7z *revoke.asc *pub.gpg *priv.gpg *trust.txt

make sure you've...

  • copied the following three backups from ~/Downloads somewhere safe (e.g. bitwarden):
    • a pub gpg key backup
    • a priv gpg key backup
    • a priv gpg subkeys backup

configuring yubikey(s)

rm -rf ~/.gnupg
del ~\AppData\Roaming\gnupg
ykman openpgp access set-retries 3 3 3 -f -a 12345678
gpg --card-edit
admin
kdf-setup | 12345678 | "OK"
passwd | 3 | 12345678 | "OK" | $ADMIN_PIN | "OK" | $ADMIN_PIN | "OK" | 1 | 123456 | "OK" | $PIN | "OK" | $PIN | "OK" | q
name | $LAST_NAME | $FIRST_NAME | $ADMIN_PIN | "OK"
lang | en
url | $URL
login | $EMAIL
key-attr | 2 | 1 | $ADMIN_PIN | "OK" | 2 | 1 | $ADMIN_PIN | "OK" | 2 | 1 | $ADMIN_PIN | "OK"
fetch
quit
gpg --import $KEY.priv.sub.gpg
 $PASSPHRASE | "OK"
gpg --edit-key $KEY
trust | 5 | y
key 1
keytocard | 1 | $PASSPHRASE | "OK" | $ADMIN_PIN | "OK"
key 1
key 2
keytocard | 2 | $PASSPHRASE | "OK"
key 2
key 3
keytocard | 3 | $PASSPHRASE | "OK"
save

note that...

  • you should repeat all steps from this section for each yubikey

configuring gpg/ssh auth

rm -rf ~/.gnupg *priv.sub.gpg
del ~\AppData\Roaming\gnupg *priv.sub.gpg
gpg --card-edit
fetch
quit
3
4
5
gpg --list-keys --keyid-format short # (1)!
gpg --list-keys --with-subkey-fingerprints # (2)!
gpg --export-ssh-key $AUTH_KEY | clip # (3)!
  1. find AUTH_KEY now
  2. find AUTH_KEYGRIP now
  3. gpg/ssh key is in the clipboard

make sure you've...

  • added the gpg/ssh key to your github user settings under ssh keys
nvim $PROFILE
$PROFILE
...
gpg-connect-agent /bye
...
New-Item -ItemType File -Path ~\AppData\Roaming\gnupg\sshcontrol
Add-Content -Path ~\AppData\Roaming\gnupg\sshcontrol -Value "$AUTH_KEYGRIP`n" -NoNewline
New-Item -ItemType File -Path ~\AppData\Roaming\gnupg\gpg.conf
Add-Content -Path ~\AppData\Roaming\gnupg\gpg.conf -Value "use-agent" -NoNewline
New-Item -ItemType File -Path ~\AppData\Roaming\gnupg\gpg-agent.conf
nvim ~\AppData\Roaming\gnupg\gpg-agent.conf 
gpg-agent.conf
1
2
3
4
5
6
enable-ssh-support
enable-putty-support
enable-win32-openssh-support
use-standard-socket
default-cache-ttl 600
max-cache-ttl 7200

configuring git

1
2
3
git config --global user.signingkey $KEY
git config --global commit.gpgsign true
git config --global tag.gpgSign true
git config --global gpg.program "C:\Program Files (x86)\GnuPG\bin\gpg.exe"

gpg tools

connecting yubikey

gpg-connect-agent "scd serialno" "learn --force" /bye

importing gpg key

make sure you've...

  • copied an old pub gpg key backup to ~/Downloads
1
2
3
4
5
cd ~/Downloads
tar -xzvf $DATE.pub.gpg.tar.gz # (1)!
gpg --import $KEY.pub.gpg # (2)!
gpg --import-ownertrust $KEY.trust.txt
rm *pub.gpg.tar.gz *pub.gpg *trust.txt
  1. DATE is the date of the pub gpg key backup to-be imported (e.g. 2025-01-01)
  2. KEY is the backed up pub gpg key id

make sure you've...

1
2
3
cd ~/Downloads
tar -xzvf $DATE.priv.gpg.tar.gz # (1)!
gpg --import $KEY.priv.gpg # (2)!
  1. DATE is the date of the priv gpg key backup to-be imported (e.g. 2025-01-01)
  2. KEY is the backed up priv gpg key id
$PASSPHRASE | "OK"
rm *priv.gpg.tar.gz *revoke.asc *priv.gpg

make sure you've...

1
2
3
cd ~/Downloads
tar -xzvf $DATE.priv.sub.gpg.tar.gz # (1)!
gpg --import $KEY.priv.sub.gpg # (2)!
  1. DATE is the date of the priv gpg subkeys backup to-be imported (e.g. 2025-01-01)
  2. KEY is the backed up priv gpg key id
$PASSPHRASE | "OK"
rm *priv.sub.gpg.tar.gz *priv.sub.gpg

revoking gpg key

make sure you've...

gpg --list-keys --keyid-format short # (1)!
gpg --edit-key $KEY
  1. find KEY now
key 1 | revkey | y | 0 | ENTER | y | $PASSPHRASE | save

make sure you've...

  • removed the pub gpg key from your github user settings under gpg keys

make sure you've...

gpg --list-keys --keyid-format short # (1)!
gpg --import $KEY.revoke.asc
  1. find KEY now

deleting gpg key

make sure you've...

gpg --list-keys --keyid-format short # (1)!
gpg --delete-secret-keys $KEY
  1. find KEY now
y | y | "Delete key" | "Delete key" | "Delete key" | "Delete key"
gpg --delete-keys $KEY
y