Skip to content

Instantly share code, notes, and snippets.

@loa
Last active April 23, 2024 17:26
Show Gist options
  • Star 24 You must be signed in to star a gist
  • Fork 5 You must be signed in to fork a gist
  • Save loa/1afeea49d60c7de7607d0d241fd489ad to your computer and use it in GitHub Desktop.
Save loa/1afeea49d60c7de7607d0d241fd489ad to your computer and use it in GitHub Desktop.
Dual GPG Yubikey Setup

Dual GPG Yubikey Setup

If you follow this guide you will end up with an offline and online Yubikey. Use your online Yubikey for everyday life, signing/encryption etc. Offline key for signing keys for web-of-trust and replace lost online keys.

Awesome tools with PGP keys:

  • mozilla/sops dead-simple local encryption of sensitive files
  • popass.pw password manager for you and your team stored in git

Offline Yubikey

Offline Yubikey for signature key, this should exclusively be used for creating/revoking online keys and signing others peoples keys for web-of-trust. This key should be kept secured and not actively used, stashed somewhere at home. For the paranoid I recommend storing the offline Yubikey in a tamper-evident bag, keep the serial of the bag in a gist (signed commits ofc). Recommended key is Yubikey 5c for future proof and to make it easy to use.

Online Yubikey

Online Yubikey for daily life. Choose a Yubikey that fits your lifestyle.

Yubikey for your keychain:

Yubikey permanent in your laptop:

Prerequisits

# Install gpg-suite
$ brew cask install gpg-suite

Make sure your Yubikeys are secure

Infineon Technologies, one of Yubico’s secure element vendors, informed us of a security issue in their firmware cryptographic libraries. The issue affects TPMs in millions of computers, and multiple smart card and security token vendors.

Make sure your key is not vulnerable on Yubico keycheck site. If it's affected then you should either buy a new Yubikey or follow a different guide how to generate the keys off the YubiKey.

Setup Offline Yubikey

Generate GPG keys on Yubikey

# Enter gpg command
$ gpg --card-edit

# Enter admin mode
gpg> admin

# Set keysize to 4096
# Choose RSA and 4096 for all options
gpg> key-attr

## Run guide to generate keypair
# Please note that the factory settings of the PINs are
#   PIN = '123456'     Admin PIN = '12345678'
# Questions with answers:
#   Make off-card backup of encryption key? (Y/n): n
#   Key is valid for?: 3y
gpg> generate

gpg> Q

Generate revocation certificate

TODO https://debian-administration.org/article/450/Generating_a_revocation_certificate_with_gpg

Add identity

Add the email addresses you want to use with your GPG identity.

When git signing it is required that committer and email address in the certificate are the same (GitHub requires this for showing verified flag). Thus you might want to have several email addresses registered in the certificate.

# We start by listing keys in your email address
$ gpg --list-keys <your email>
pub   rsa4096 2018-02-05 [SC] [expires: 2022-02-12]
      EA85C6564606A899966AB7F175745A53C9673583
uid           [ultimate] Carl Loa Odin <loa@nonetype.se>
sub   rsa4096 2018-02-05 [A] [expires: 2022-02-12]
sub   rsa4096 2018-02-05 [E] [expires: 2022-02-12]

# copy the key id from previous listing (in example EA85C6564606A899966AB7F175745A53C9673583)
$ gpg --expert --edit-key <longid>

# for every email you want to add run
gpg> adduid

# now select the uid you want as your primary, probably your private email address
gpg> uid 2
gpg> primary

gpg> save

Secure Offline Yubikey

# Enter gpg command
$ gpg --card-edit

# Step into admin mode
gpg> admin

# Config Yubikey with your name
gpg> name

# Require pin for all signatures
gpg> forcesig

# Enter password menu to set personal PIN and admin PIN
gpg> passwd

# Update personal PIN
gpg> 1

# Update Admin Pin
gpg> 3

gpg> quit

Setup Online Yubikey

We will now setup a secondary yubikey with subkeys. This one will be for everyday usage.

Generate subkeys

IMPORTANT: Make sure only your offline Yubikey is plugged in which contains your main key.

# We start by listing keys in your email address
$ gpg --list-keys <your email>
pub   rsa4096 2018-02-05 [SC] [expires: 2022-02-12]
      EA85C6564606A899966AB7F175745A53C9673583
uid           [ultimate] Carl Loa Odin <loa@nonetype.se>
sub   rsa4096 2018-02-05 [A] [expires: 2022-02-12]
sub   rsa4096 2018-02-05 [E] [expires: 2022-02-12]

# copy the key id from previous listing (in example EA85C6564606A899966AB7F175745A53C9673583)
$ gpg --expert --edit-key <longid>

# Generate new subkey for signatures
# Questions with answers:
#   Please select what kind of key you want (4) RSA (sign only): 4
#   RSA keys may be between 1024 and 4096 bits long: 4096
#   Please specify how long the key should be valid: 3y
gpg> addkey

# Generate new subkey for encryption
# Questions with answers:
#   Please select what kind of key you want (6) RSA (encrypt only): 6
#   RSA keys may be between 1024 and 4096 bits long: 4096
#   Please specify how long the key should be valid: 3y
gpg> addkey

# Generate new subkey for authentication
# Questions with answers:
#   Please select what kind of key you want (8) RSA (set your own capabilities): 8
#   Toggle capabilities until only Authentication is choosen: _Current allowed actions: Authenticate_
#   RSA keys may be between 1024 and 4096 bits long: 4096
#   Please specify how long the key should be valid: 3y
gpg> addkey

gpg> save

Secure Online Yubikey

IMPORTANT: Make sure only your Online Yubikey is plugged in which is currently empty.

# Enter gpg command
$ gpg --card-edit

# Step into admin mode
gpg> admin

# Config Yubikey with your name
gpg> name

# Require pin for all signatures
gpg> forcesig

# Enter password menu to set personal PIN and admin PIN
gpg> passwd

# Update personal PIN
gpg> 1

# Update Admin Pin
gpg> 3

gpg> quit

Move subkeys to Online Yubikey

IMPORTANT: Make sure only your new Online Yubikey is plugged in.

# We start by listing keys in your email address (notice the extra subkeys generated in previous steps)
$ gpg --list-keys <your email>
pub   rsa4096 2018-02-05 [SC] [expires: 2022-02-12]
      EA85C6564606A899966AB7F175745A53C9673583
uid           [ultimate] Carl Loa Odin <loa@nonetype.se>
sub   rsa4096 2018-02-05 [A] [expires: 2022-02-12]
sub   rsa4096 2018-02-05 [E] [expires: 2022-02-12]
sub   rsa4096 2018-12-18 [S] [expires: 2022-12-17]
sub   rsa4096 2018-12-18 [E] [expires: 2022-12-17]
sub   rsa4096 2018-12-18 [A] [expires: 2022-12-17]

# copy the key id from previous listing (in example EA85C6564606A899966AB7F175745A53C9673583)
$ gpg --expert --edit-key <longid>

# make it possible to select individual keys
gpg> toggle

# Select the last key with usage S, probably key 3.
# The key should be marked with a `ssb*`
gpg> key 3

sec  rsa4096/75745A53C9673583
     created: 2018-02-05  expires: 2022-02-12  usage: SC
     card-no: 0006 07431439
     trust: unknown       validity: ultimate
ssb  rsa4096/4CD49BFD4E4F10D3
     created: 2018-02-05  expires: 2022-02-12  usage: A
     card-no: 0006 07431439
ssb  rsa4096/AF20A2CB05BEC84E
     created: 2018-02-05  expires: 2022-02-12  usage: E
     card-no: 0006 07431439
ssb* rsa4096/ABBF2E2607AC076B
     created: 2018-12-18  expires: 2022-12-17  usage: S
ssb  rsa4096/A6D37B9DF8529809
     created: 2018-12-18  expires: 2022-12-17  usage: E
ssb  rsa4096/A49F7D3A02291CA3
     created: 2018-12-18  expires: 2022-12-17  usage: A
[ultimate] (1). Carl Loa Odin <loa@nonetype.se>

# Move signature subkey to yubikey
# Questions with answers:
#   Please select where to store the key (1) Signature key: 1
gpg> keytocard

# Deselect signature key
gpg> key 3

# Select the last key with usage E, probably key 4.
# The key should be marked with a `ssb*`
gpg> key 4

# Move encryption subkey to yubikey
# Questions with answers:
#   Please select where to store the key (2) Encryption key: 2
gpg> keytocard

# Deselect encryption key
gpg> key 4

# Select the last key with usage A, probably key 5.
# The key should be marked with a `ssb*`
gpg> key 5

# Move authentication subkey to yubikey
# Questions with answers:
#   Please select where to store the key (3) Authentication key: 3
gpg> keytocard

gpg> save

Quick verification of Dual Yubikey Setup

# We start by listing keys in your email address (notice the extra subkeys generated in previous steps)
$ gpg --list-keys <your email>
pub   rsa4096 2018-02-05 [SC] [expires: 2022-02-12]
      EA85C6564606A899966AB7F175745A53C9673583
uid           [ultimate] Carl Loa Odin <loa@nonetype.se>
sub   rsa4096 2018-02-05 [A] [expires: 2022-02-12]
sub   rsa4096 2018-02-05 [E] [expires: 2022-02-12]
sub   rsa4096 2018-12-18 [S] [expires: 2022-12-17]
sub   rsa4096 2018-12-18 [E] [expires: 2022-12-17]
sub   rsa4096 2018-12-18 [A] [expires: 2022-12-17]

# copy the key id from previous listing (in example EA85C6564606A899966AB7F175745A53C9673583)
$ gpg --expert --edit-key <longid>

$ quit

Verify following from the output given from the commands above:

  • All keys are assigned to a card:
    card-no: 0006 07431439
    
  • First keys SC, A, E are assigned to one card
    card-no: 0006 07431439
    
  • Last keys S, E, A are assigned to another card
    card-no: 0006 08626967
    
gpg (GnuPG/MacGPG2) 2.2.10; Copyright (C) 2018 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/75745A53C9673583
     created: 2018-02-05  expires: 2022-02-12  usage: SC
     card-no: 0006 07431439
     trust: unknown       validity: ultimate
ssb  rsa4096/4CD49BFD4E4F10D3
     created: 2018-02-05  expires: 2022-02-12  usage: A
     card-no: 0006 07431439
ssb  rsa4096/AF20A2CB05BEC84E
     created: 2018-02-05  expires: 2022-02-12  usage: E
     card-no: 0006 07431439
ssb  rsa4096/ABBF2E2607AC076B
     created: 2018-12-18  expires: 2022-12-17  usage: S
     card-no: 0006 08626967
ssb  rsa4096/A6D37B9DF8529809
     created: 2018-12-18  expires: 2022-12-17  usage: E
     card-no: 0006 08626967
ssb  rsa4096/A49F7D3A02291CA3
     created: 2018-12-18  expires: 2022-12-17  usage: A
     card-no: 0006 08626967
[ultimate] (1). Carl Loa Odin <loa@nonetype.se>

What do I do now?

  1. Lock/hide away your offline yubikey with your primary signature key at home or bank safe
  2. Keep your online everyday yubikey with you and enjoy life with GPG
  3. Publish your public key to the world
  4. Go to key-signing parties

Setup gpg-agent for SSH authentication

This will setup gpg-agent as your ssh-agent so the key on the Yubikey is exposed for ssh authentication.

# Create config dir for gpg
$ mkdir ~/.gnupg

# Create config for gpg-agent
$ cat > ~/.gnupg/gpg-agent.conf <<EOF
enable-ssh-support
EOF

Add following to your .bashrc or .zshrc:

export SSH_AUTH_SOCK="/run/user/$(id -u)/gnupg/S.gpg-agent.ssh"

Restart shell and run following to verify:

$ ssh-add -L
ssh-rsa AAAAB...== cardno:000000000000

QA

Howto use Yubikey for git commit/tag signing

You can setup git to sign commits and tags with the keys on your Yubikey.

# Identify your key id, 866BB649D084C1BA0E877C1A3C3AD83C0E508BDD in this example
$ gpg --list-keys <your email>
pub   rsa4096 2018-02-05 [SC] [expires: 2022-02-12]
      EA85C6564606A899966AB7F175745A53C9673583
uid           [ultimate] Carl Loa Odin <loa@nonetype.se>
sub   rsa4096 2018-02-05 [A] [expires: 2022-02-12]
sub   rsa4096 2018-02-05 [E] [expires: 2022-02-12]

# Set git signing key globally
$ git config --global user.signingkey EA85C6564606A899966AB7F175745A53C9673583

## GitHub show Verified on keys
# You can add your public key to your GitHub profile so your commits shows up as verified
# Export the public key in ascii format and add as a new GPG key https://github.com/settings/keys
$ gpg --armor --export EA85C6564606A899966AB7F175745A53C9673583

# Add -S to sign commits
$ git commit -S -m "Test commit"

# Use -s instead of -a to sign git tags
$ git tag -s v1.5 -m 'my signed 1.5 tag'

# Add --show-signature to view signature on commits
$ git show --show-signature

# Run following to always sign commits
$ git config --global commit.gpgsign true

References:

@jonnisell
Copy link

If you have a Yubikey and want to reset the current keys on that Yubikey, use this script https://gist.github.com/pkirkovsky/c3d703633effbdfcb48c#file-yubikey-reset-sh

@sgal
Copy link

sgal commented Feb 5, 2019

If you're on OSX Mojave and your Mail.app stopped working after installing gpg-suite - try following guide, or just imply run (after closing Mail.app)

rm -rf ~/Library/Containers/com.apple.mail/Data/DataVaults

@sgal
Copy link

sgal commented Feb 5, 2019

If you have issues running gpgconf or gpg-agent -> make sure that gpg-suite stuff is in the PATH. brew-cask does not add it (for some reason), so to fix it - just add following line to your .bashrc or .zshrc

export PATH=/url/local/bin:/usr/local/MacGPG2/bin:$PATH

And restart your terminal.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment