Skip to content

Instantly share code, notes, and snippets.

@JoeCalvert
Last active February 23, 2026 15:52
Show Gist options
  • Select an option

  • Save JoeCalvert/11d14360d51f0032a7d400970afe6a2a to your computer and use it in GitHub Desktop.

Select an option

Save JoeCalvert/11d14360d51f0032a7d400970afe6a2a to your computer and use it in GitHub Desktop.
Setup Windows Hello/YubiKey SSH Auth

SSH Authentication and Git Signing with Windows Hello or YubiKey on Windows and WSL2

This guide explains how to use Windows Hello (backed by a TPM 2.0) or a YubiKey for SSH authentication and Git commit signing on a Windows machine, including integration with WSL2 and VS Code DevContainers.

Table of Contents:

  1. Prerequisites
  2. Key Generation
  3. Setting up Git Signing with SSH
  4. Using with WSL2
  5. Using with VS Code DevContainers
  6. Importing YubiKey Discoverable Keys on a New Machine
  7. Troubleshooting

1. Prerequisites

  • OpenSSH Client: Version 8.3 or later (check with ssh -V).
  • YubiKey: A FIDO2-compliant YubiKey
  • Windows Machine with TPM 2.0: For Windows Hello integration, you need a TPM 2.0 chip and Windows Hello set up
  • Git: Version 2.34 or later (check with git --version).
  • WSL2: Installed and configured.
  • npiperelay: Required for communication between WSL2 and the Windows OpenSSH agent.

2. Key Generation

Generate SSH keys using either a YubiKey or Windows Hello. These keys will be used for both SSH authentication and Git signing.

YubiKey

Choosing a Key Type:

  • ed25519-sk: Provides stronger security and is generally recommended. Use this if your YubiKey and SSH server support it.
  • ecdsa-sk: An alternative if ed25519-sk is not supported.

Discoverable vs. Non-Discoverable Credentials:

  • Discoverable (Resident) Credentials: Stored on the YubiKey itself. This allows you to use the key on different machines without needing to export and import it, but limits the number of keys stored to around 25, depending on your YubiKey's storage capacity. Requires generating the key with the -O resident flag.
  • Non-Discoverable Credentials: Not stored on the YubiKey. You'll need to back up and restore these keys manually when moving to a new machine.

Generating the Key:

  1. Open a terminal (Command Prompt or PowerShell).

  2. Run one of the following commands:

    • Discoverable Credential (Recommended):

      ssh-keygen -t ed25519-sk -O resident -O application=ssh:<YourAppName> -O verify-required -C "<YourComment>"

      or

      ssh-keygen -t ecdsa-sk -O resident -O application=ssh:<YourAppName> -O verify-required -C "<YourComment>"
      • -t ed25519-sk or -t ecdsa-sk: Specifies the key type (choose one).
      • -O resident: Makes the key discoverable (stored on the YubiKey).
      • -O application=ssh:<YourAppName>: Sets the application parameter to ssh: followed by your app's name. This can be useful for organization, but it's optional.
      • -O verify-required: Requires user verification (usually a PIN) for each use.
      • -C "<YourComment>": Adds a comment to the key (e.g., your email address or a description).
      • The key will be stored in ~/.ssh/ by default.
    • Non-Discoverable Credential:

      ssh-keygen -t ed25519-sk -C "<YourComment>"

      or

      ssh-keygen -t ecdsa-sk -C "<YourComment>"
      • -t ed25519-sk or -t ecdsa-sk: Specifies the key type.
      • -C "<YourComment>": Adds a comment to the key.
  3. Follow the prompts: You'll be asked to touch your YubiKey and potentially enter/create a PIN.

Windows Hello

  1. Open a terminal (Command Prompt or PowerShell).

  2. Run the following command:

    ssh-keygen -t ecdsa-sk -C "<YourComment>"
    • -t ecdsa-sk: Specifies the key type (currently, only ecdsa-sk is supported with Windows Hello).
    • -C "<YourComment>": Adds a comment to the key.
  3. Follow the prompts: You'll be asked to authenticate using Windows Hello (PIN, fingerprint, etc.).

3. Setting up Git Signing with SSH

Configure Git to use your newly generated SSH key for signing commits.

Configure Git

  1. Set the GPG signing format to SSH:

    git config --global gpg.format ssh
  2. Set your signing key:

    git config --global user.signingKey ~/.ssh/<YourPublicKey>
    • Replace <YourPublicKey> with the actual name of your public key file (e.g., id_ed25519_sk.pub, id_ecdsa_sk.pub).

    • For Windows Hello, I like to name the key tpm_ecdsa_sk.pub on every machine. This means I can use the same Git config and DevContainer configuration across different machines.

  3. Enable commit signing by default (Optional):

    git config --global commit.gpgSign true
    • If you don't enable this, you'll need to use the -S flag every time you commit: git commit -S -m "Your commit message"

Create Allowed Signers File

Git uses an "allowed signers" file to verify SSH signatures. You need to create this file and add your public key to it.

  1. Create the file:

    mkdir -p ~/.ssh
    touch ~/.ssh/allowed_signers
  2. Add your public key to the file:

    echo "git@github.com $(cat ~/.ssh/<YourPublicKey>)" >> ~/.ssh/allowed_signers
    • Replace <YourPublicKey> with the name of your public key file (e.g., id_ed25519_sk, id_ecdsa_sk).
    • Replace git@github.com with the appropriate entry for your Git provider (e.g., git@gitlab.com, git@bitbucket.org, or your own server's address). You might need multiple lines if you use multiple providers.
  3. Tell Git about your allowed signers file:

    git config --global gpg.ssh.allowedSignersFile ~/.ssh/allowed_signers

4. Using with WSL2

To use your Windows-generated SSH key within WSL2, the Windows OpenSSH agent and npiperelay are needed to forward the authentication requests.

Windows Setup

  1. Build npiperelay:

    • Go to the npiperelay GitHub repository.
    • Follow the instructions in the README
    • Place the compiled npiperelay.exe in a directory on your Windows system (e.g., C:\npiperelay).
  2. Enable and Start the OpenSSH Agent:

    • Open PowerShell as an administrator.

    • Run the following commands:

      Set-Service ssh-agent -StartupType Automatic
      Start-Service ssh-agent
      Get-Service ssh-agent # Verify that the status is "Running"

WSL Setup

  1. Install socat:

    • Open your WSL2 terminal.

    • Run:

      sudo apt update
      sudo apt install socat
  2. Enable WSL Interop:

    • Run:

      sudo sh -c 'echo :WSLInterop:M::MZ::/init:PF > /usr/lib/binfmt.d/WSLInterop.conf'

      This command allows WSL to execute Windows binaries.

Configure WSL's .bashrc

  1. Open your .bashrc file:

    nano ~/.bashrc
  2. Add these lines at the end of the file:

      export SSH_AUTH_SOCK="$HOME/.ssh/ssh-auth.socket"
    
      ss -a | grep -q "$SSH_AUTH_SOCK"
      if [ $? -ne 0 ]; then
          rm -f "$SSH_AUTH_SOCK"
          (setsid socat UNIX-LISTEN:"$SSH_AUTH_SOCK",fork EXEC:"/mnt/c/npiperelay/npiperelay.exe -ei -s //./pipe/openssh-ssh-agent" &) >/dev/null 2>&1
      fi
    • export SSH_AUTH_SOCK="$HOME/.ssh/ssh-auth.socket": Sets the SSH_AUTH_SOCK environment variable to a custom path. This variable tells SSH clients where to find the SSH agent's socket.
    • ss -a | grep -q "$SSH_AUTH_SOCK": Checks if there is already a process listening on the socket specified by SSH_AUTH_SOCK. This prevents multiple instances from running.
    • rm -f "$SSH_AUTH_SOCK": Removes the socket file if no process is listening on it, ensuring a clean start.
    • setsid socat ... : This is the forwarding setup:
      • setsid: Creates a new session for the socat process, detaching it from the current terminal. This allows the forwarding to continue even after you close the terminal.
      • socat: A powerful utility for bidirectional data transfer. Here, it's used to create a Unix socket and forward connections to npiperelay.exe.
      • UNIX-LISTEN:"$SSH_AUTH_SOCK",fork: Tells socat to listen on a Unix socket at the path specified by SSH_AUTH_SOCK and to fork a new process for each incoming connection.
      • EXEC:"/mnt/c/npiperelay/npiperelay.exe -ei -s //./pipe/openssh-ssh-agent" Specifies the command to execute for each connection. This runs npiperelay.exe, which forwards the connection to the Windows OpenSSH agent's named pipe (//./pipe/openssh-ssh-agent).
      • -ei: Forwards standard input and output.
      • -s: Uses a named pipe.
  3. Use the new .bashrc:

    source ~/.bashrc

Copy the Public Key to WSL

5. Using with VS Code DevContainers

To use your key in VS Code DevContainers you need to enable SSH Agent Forwarding:

 ```json
 "settings": {
     "remote.SSH.enableAgentForwarding": true
 }
 ```

6. Importing YubiKey Discoverable Keys on a New Machine

If you used a discoverable (resident) key with your YubiKey, you can "import" it on a new machine:

  1. Insert your YubiKey.

  2. Open PowerShell as an administrator.

  3. Navigate to your .ssh directory:

    cd ~/.ssh
  4. Run:

    ssh-keygen -K

    This command will import the resident keys from your YubiKey, storing them as stubs in your ~/.ssh directory.

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