YubiKey Setup and Usage Guide:
SSH, Git Signing, and More

Last updated: April 13, 2025

1. Introduction: What is a YubiKey?

A YubiKey is a hardware security key developed by Yubico. It provides a phishing-resistant method for two-factor authentication (2FA), multi-factor authentication (MFA), and managing cryptographic keys for tasks like SSH access and code signing. By storing cryptographic secrets on a dedicated hardware device, YubiKeys significantly enhance security compared to software-based authenticators or passwords alone.

YubiKeys support various protocols, including:

  • FIDO2/WebAuthn & U2F: For strong, passwordless web authentication.
  • PIV (Personal Identity Verification): Smart card standard often used for SSH and system login.
  • OpenPGP: For email encryption and code signing (used for SSH and Git).
  • OTP (One-Time Password): Yubico OTP and OATH standards.

This guide focuses on setting up your host system to interact with the YubiKey and utilizing its PIV and OpenPGP capabilities for secure SSH access and Git commit/tag signing.

2. Initial YubiKey Setup (Host System)

Before using advanced features like SSH or GPG, you need to ensure your computer can communicate with the YubiKey and has the necessary management software installed.

2.1 Essential Tools

Two primary tools from Yubico are generally needed:

  • YubiKey Manager: A GUI and command-line tool (ykman) for configuring various YubiKey features (FIDO2, OTP, PIV interfaces, etc.).
  • Yubico Authenticator: A desktop and mobile application for managing OATH TOTP/HOTP credentials stored on the YubiKey. (Not covered in detail here, but good to have).

Additionally, for GPG/SSH integration, you'll need the GnuPG suite and potentially OpenSC or specific PKCS#11 libraries.

2.2 Windows Setup

  1. Drivers: Modern Windows versions usually install necessary drivers automatically when you plug in the YubiKey.
  2. Install YubiKey Manager: Download and install the YubiKey Manager application from the official Yubico website.
  3. Install GnuPG (Optional, for GPG/SSH/Git): Download and install Gpg4win, which includes GnuPG, Kleopatra (GUI), and GpgOL (Outlook plugin).
  4. Install OpenSSH Client (if needed): Windows 10/11 include an OpenSSH client, but ensure it's enabled (Settings > Apps > Optional features).

2.3 macOS Setup

  1. Install YubiKey Manager: Download from the Yubico website or install via Homebrew:
    brew install --cask yubikey-manager
  2. Install GnuPG (Optional, for GPG/SSH/Git): Use Homebrew:
    brew install gnupg pinentry-mac
    Configure GPG Agent to use pinentry-mac by adding pinentry-program /opt/homebrew/bin/pinentry-mac (path may vary) to ~/.gnupg/gpg-agent.conf.
  3. SSH: macOS includes OpenSSH. You might need OpenSC for PIV-based SSH:
    brew install opensc

2.4 Linux Setup

Package names may vary slightly based on your distribution.

  1. Install YubiKey Manager: Often available via package manager:
    # Debian/Ubuntu
    sudo apt update
    sudo apt install yubikey-manager
    
    # Fedora/CentOS/RHEL
    sudo dnf install yubikey-manager
    Alternatively, use the AppImage from Yubico's website.
  2. Install GnuPG & Smart Card Daemons (Optional, for GPG/SSH/Git):
    # Debian/Ubuntu
    sudo apt install gnupg pcscd scdaemon libccid
    
    # Fedora/CentOS/RHEL
    sudo dnf install gnupg pcsc-lite ccid
  3. Install OpenSC (Optional, for PIV SSH):
    # Debian/Ubuntu
    sudo apt install opensc
    
    # Fedora/CentOS/RHEL
    sudo dnf install opensc
  4. Udev Rules: To allow non-root access to the YubiKey, install Yubico's udev rules:
    # Usually installed with yubikey-manager or yubikey-personalization
    # Or manually download from Yubico/GitHub and place in /etc/udev/rules.d/
    sudo udevadm control --reload-rules && sudo udevadm trigger
  5. Enable/Start Services: Ensure pcscd service is running:
    sudo systemctl enable pcscd.service
    sudo systemctl start pcscd.service

Once these tools are installed, you can plug in your YubiKey and use YubiKey Manager or gpg --card-status to verify detection.

3. Using YubiKey as an SSH Key

Storing your SSH private key (or a reference) on the YubiKey means the key never leaves the hardware, providing strong protection against theft. Authentication requires the key to be present and often a PIN and/or touch.

3.1 Method 1: Using the PIV Applet

The PIV (Personal Identity Verification) applet provides smart card functionality, including storing key pairs for authentication (slot 9a).

  1. Generate Key Pair on YubiKey (using ykman):
    # Generate a new ECC P256 key in slot 9a (Authentication)
    # You will be prompted for the Management Key (default: 010203040506070801020304050607080102030405060708 - CHANGE THIS!) and PIN
    ykman piv keys generate 9a --pin-policy=ONCE --touch-policy=ALWAYS public.pem
    
    # (Optional) Generate a self-signed certificate for the key
    ykman piv certificates generate 9a public.pem -s "Your Name SSH" --pin-policy=ONCE --touch-policy=ALWAYS
    This saves the public key to public.pem. The private key remains securely on the YubiKey. Note the PIN/Touch policies (ONCE = ask PIN once per session, ALWAYS = ask PIN every time; ALWAYS touch = require touch every time).
  2. Get Public Key in SSH Format: You need a PKCS#11 library that understands YubiKey PIV. OpenSC is common. The path varies by OS.
    # Example for macOS with OpenSC via Homebrew
    ssh-keygen -D /opt/homebrew/lib/opensc-pkcs11.so
    
    # Example for Linux (path might differ)
    ssh-keygen -D /usr/lib/x86_64-linux-gnu/opensc-pkcs11.so 
    Copy the specific public key output corresponding to slot 9a.
  3. Configure SSH Agent: Tell your SSH agent to use the YubiKey via the PKCS#11 library.
    # Add the key to the agent (requires agent running)
    ssh-add -s /path/to/your/opensc-pkcs11.so 
    # You might be prompted for your YubiKey PIV PIN
    Ensure your SSH agent is running (eval $(ssh-agent -s) if needed). You may need to add this ssh-add command to your shell startup file (.bashrc, .zshrc).

3.2 Method 2: Using OpenPGP via GPG Agent

This method leverages the OpenPGP applet on the YubiKey and GnuPG tools.

  1. Generate/Import GPG Key: Ensure you have a GPG key pair with an Authentication subkey stored on your YubiKey. You can generate one directly on the key:
    gpg --expert --full-gen-key
    # Choose "(9) ECC (sign and encrypt)" + "(1) Curve 25519" (or RSA)
    # Choose key size (if RSA)
    # Choose validity period
    # Enter user ID info
    # When prompted for actions after generation, choose actions to create Sign, Encrypt, Authenticate subkeys and move them to the card.
    Alternatively, generate keys offline and use gpg --edit-key [KEY_ID] commands (keytocard) to move subkeys. Ensure you have an [A]uthentication subkey on the card.
  2. Configure GPG Agent for SSH: Edit ~/.gnupg/gpg-agent.conf (create if needed) and add/uncomment:
    enable-ssh-support
    Restart the agent: gpg-connect-agent reloadagent /bye.
  3. Export SSH Public Key: Find the keygrip of your Authentication subkey (gpg --list-keys --with-keygrip), then tell GPG agent to use it by adding the keygrip to ~/.gnupg/sshcontrol. Alternatively, get the public key directly:
    # Option 1: List keys known to the agent
    ssh-add -L 
    
    # Option 2: Export specific key using GPG Key ID (find with gpg --list-keys)
    gpg --export-ssh-key [YOUR_GPG_KEY_ID]!
    (The ! after the Key ID specifically targets the authentication subkey if available). Copy the output starting with ssh-rsa or ecdsa-sha2-nistp256 etc.
  4. Configure SSH Client: Ensure SSH uses the GPG agent socket. Add to your shell startup file (.bashrc, .zshrc):
    unset SSH_AGENT_PID
    export SSH_AUTH_SOCK=$(gpgconf --list-dirs agent-ssh-socket)
    Reload your shell configuration (source ~/.bashrc) or restart your shell/terminal.

3.3 Server Configuration

Regardless of the method used (PIV or GPG), you need to add the exported SSH public key to the ~/.ssh/authorized_keys file on the server(s) you want to connect to.

# On the remote server
echo "PASTE_YOUR_EXPORTED_PUBLIC_KEY_HERE" >> ~/.ssh/authorized_keys
chmod 600 ~/.ssh/authorized_keys

Now, when you SSH (ssh user@hostname), your SSH client (via the agent configured for PIV or GPG) should prompt for your YubiKey PIN and/or touch, using the key on the hardware for authentication.

4. Using YubiKey for Git Signatures

Signing Git commits and tags cryptographically verifies that you are the author and that the code hasn't been tampered with since you signed it. This uses the GPG key stored on your YubiKey's OpenPGP applet.

4.1 GPG Key Setup on YubiKey

You need a GPG key pair with a Signing subkey stored on your YubiKey.

  1. Follow the steps in section 3.2 (Method 2 for SSH) to generate or import GPG keys onto your YubiKey using gpg. Ensure you have a subkey with the [S]igning capability on the card.
  2. Verify with gpg --card-status.

4.2 Configuring Git

Tell Git which GPG key to use for signing:

  1. Find your GPG Key ID: Use the key ID (usually the last 8 or 16 hex characters) of the primary key associated with the signing subkey on your YubiKey.
    gpg --list-secret-keys --keyid-format LONG
    Look for the line starting sec. The ID is after the /.
  2. Configure Git Globally:
    # Replace YOUR_KEY_ID with the ID found above
    git config --global user.signingkey YOUR_KEY_ID
    
    # Optional: Sign all commits by default
    git config --global commit.gpgsign true
    
    # Optional: Sign all tags by default (recommended for releases)
    git config --global tag.gpgsign true
    
    # Ensure Git uses the correct GPG program
    # Usually 'gpg' is fine, but specify full path if needed
    git config --global gpg.program gpg 
  3. Ensure GPG Agent is Running: Git relies on gpg-agent to handle communication with the YubiKey and prompt for the PIN via pinentry. Make sure it's running (often started automatically when needed).

4.3 Signing Commits and Tags

  • If you set commit.gpgsign true, commits will be signed automatically:
    git commit -m "My signed commit"
  • To sign manually (if default is false):
    git commit -S -m "My explicitly signed commit"
  • To sign a tag (annotated tag required for signing):
    # If tag.gpgsign true:
    git tag -a v1.0 -m "Version 1.0 release"
    
    # To sign manually or override default:
    git tag -s v1.0 -m "Version 1.0 release"
  • You will be prompted for your YubiKey GPG PIN (and potentially touch) when signing.
  • Verify signatures using git log --show-signature or git tag -v [tagname]. Platforms like GitHub and GitLab will often display a "Verified" badge next to signed commits/tags associated with a public key uploaded to your profile.

5. Using Your YubiKey on a Different Machine

One of the key benefits of using a hardware key like the YubiKey is that your private keys (SSH, GPG) *never leave the device*. To use your already-configured YubiKey on a new computer, you don't re-configure the key itself; instead, you set up the *new computer* to recognize and interact with the YubiKey.

The steps are essentially repeating the relevant host setup parts from section 2 and configuring the applications (SSH, Git) on the new machine:

  1. Install Host Software: On the new machine, install the necessary tools: YubiKey Manager, GnuPG suite (gpg, gpg-agent), pcscd, scdaemon, pinentry, and potentially opensc or the relevant PKCS#11 library if using PIV for SSH. Refer to sections 2.2, 2.3, or 2.4 for OS-specific installation. Ensure services like pcscd are running and udev rules (Linux) are in place.
  2. Configure GPG Agent (for GPG SSH/Git):
    • Create/edit ~/.gnupg/gpg-agent.conf on the new machine.
    • Add enable-ssh-support if using it for SSH.
    • Configure pinentry-program if needed (especially macOS).
    • Restart the agent: gpg-connect-agent reloadagent /bye.
  3. Configure SSH Client:
    • If using GPG Agent: Set the SSH_AUTH_SOCK environment variable to point to the GPG agent socket in your shell startup file (see section 3.2, step 4). Verify with ssh-add -L.
    • If using PIV: Add the key via the PKCS#11 library using ssh-add -s /path/to/pkcs11/library.so (see section 3.1, step 3). You might add this to your shell startup.
  4. Configure Git (for Signing):
    • Set the global Git configuration on the new machine:
      git config --global user.signingkey YOUR_KEY_ID
      git config --global commit.gpgsign true  # Or false
      git config --global gpg.program gpg
  5. Verify: Plug in your YubiKey. Try gpg --card-status, ssh user@host, or git commit. You should be prompted for your YubiKey PIN/touch by the agent/system on the new machine.

You do not need to run ykman piv keys generate or gpg --expert --full-gen-key again. The keys are already securely stored on your YubiKey; you're just telling the new computer how to talk to it.

6. Conclusion & Best Practices

Using a YubiKey for SSH authentication and Git signing significantly enhances your security posture by keeping private keys off your computer's main storage. Setting it up involves configuring your host operating system and applications (SSH, GPG, Git) to interact with the hardware device.

Best Practices:

  • Strong PINs: Change the default PIV and GPG PINs/Admin PINs (Management Key) to strong, unique values using YubiKey Manager or gpg --change-pin.
  • Backup Key: Consider purchasing a second YubiKey and configuring it similarly as a backup in case your primary key is lost or damaged. Store it securely.
  • Key Management: Keep track of which keys (PIV, GPG subkeys) are on your YubiKey.
  • Touch Policy: Use touch policies (--touch-policy=ALWAYS or similar) for sensitive operations like SSH authentication or signing to prevent unintended use if the key is plugged in and unlocked.
  • Firmware Updates: Occasionally check for YubiKey firmware updates via Yubico's channels, although updates are less frequent than software.

While the initial setup requires understanding several tools and concepts, the enhanced security and convenience of hardware-backed keys are well worth the effort for developers and security-conscious users.

7. Additional Resources

Related Articles

External Resources