Introduction

I recently switched to Fedora 26 (due to working environment) and I would like to use YubiKey to maximize security and re-use existing credentials.

GPG Keys

GPG keys can be written into YubiKey with references to this official document. However, there is some point to notice. Firstly, due to an issue of YubiKey's upstream manufacturer[1], on-chip RSA generation should not be used on my YubiKey, and may be yours either. The second is, creating and using sub-keys is often considered safer than writing your main key.
Creating GPG keys is simple. Use

$ gpg2 --full-generate-key

then follow the guides to generate a master key. Now, the master key is generated but should not be used. GPG has a master-slave hierarchy. The Best practices are always keeping master key safe and use sub-keys.
Before we generate sub-keys, we can see how many and what keys a Yubikey 4 could store.

$ gpg2 --card-status                                                                                                    ....
Key attributes ...: rsa4096 rsa4096 rsa4096
....
Signature key ....: $_FINGERPRINT
      created ....: $_DATE
Encryption key....: $_FINGERPRINT
      created ....: $_DATE
Authentication key: $_FINGERPRINT
      created ....: $_DATE
....

It could be clearly found that a Yubikey 4 could store 3 keys for signing, encryting and authentication respectively. To generate a sub-key and write it into Yubikey (and any other smart-card), use

$ gpg --expert --edit-key $KEYID

Then use addkey and follow the guides. When sub-keys are ready, make a backup of your keys and (most importantly) master key.

$ gpg --armor --export-secret-keys $KEYID > $GNUPGHOME/mastersub.key
$ gpg --armor --export-secret-subkeys $KEYID > $GNUPGHOME/sub.key

Finally, use keytocard command in gpg2 to transfer it into Yubikey.

gpg> keytocard
Please select where to store the key:
   (1) Signature key
   (3) Authentication key
Your selection? 1

SSH

SSH keys are exported from GPG. This could be easily done by gpg. On every session which you want to use you exported SSH keys, you just have to ensure the gpg-agent is running, and SSH_AUTH_SOCKS has been correctly exported.
To enable GPG-exported SSH keys, first add the enable-ssh-support option to gpg:

echo "enable-ssh-support" >> ~/.gnupg/gpg-agent.conf

Then add the following to .zshrc (or .bashrc if you are using bash) to export SSH_AUT_SOCKS automatically:

# GPG Agent (SSH Key) configurations
unset SSH_AGENT_PID
gpg-agent --daemon &> /dev/null
export SSH_AUTH_SOCK="$(gpgconf --list-dirs agent-ssh-socket)"

Or, if you use oh-my-zsh, you can simple enable gpg-agent plugin.

Universal 2nd Factor (U2F) and PAM

There is 2 ways to integrate YubiKey into pam.d, which are pam-u2f and yubico-pam. The former takes the advantages of U2F and is compatible with other U2F token, while the latter utilizes Yubico OTP. I would like to use a general way, so here is how to configure pam.d to use U2F.

U2F Integration into PAM

  1. First of all we need to install pam-u2f. Under Fedora, it could be easily installed using sudo dnf install pam-u2f.
  2. Then we need to generate a file to record which token for which corresponding user. It could be done by pamu2fcfg > ~/.config/Yubico/u2f_keys.
  3. Then open /etc/pam.d/system-auth, and add auth sufficient pam_u2f.so cue to a suitable line[2]. In this line, cue indicates pam-u2f to prompt user to touch the device when required. We can actually edit other file(s) in /etc/pam.d/ to customize.

  1. This issue has been fixed since firmware 4.3.5, and replacement project has been carried out. There is an official announcement. ↩︎

  2. If you want to know more, you can refer to this blog post. ↩︎