ssh-keygen -t ed25519-sk -O resident -O application=ssh:<your-username>-signing -O user=<your-username> -C "<your-email>" -f "$env:USERPROFILE\.ssh\id_ed25519_sk_<your-username>-signing"Key flags:
-t ed25519-sk— hardware-backed FIDO2 key-O resident— key material stored on the YubiKey (survives machine wipes)-O application=ssh:<your-username>-signing— labels the credential slot on the key-O user=<your-username>— sets a non-null user handle (required to avoid "user id null" error)-O verify-required— optionally add this if you want PIN required on use
Get-Content "$env:USERPROFILE\.ssh\id_ed25519_sk_<your-username>-signing.pub"git config gpg.format ssh
git config user.signingkey "$env:USERPROFILE\.ssh\id_ed25519_sk_<your-username>-signing.pub"
git config commit.gpgsign true
git config tag.gpgsign trueUse --global to apply to all repos instead.
New-Item -Force "$env:USERPROFILE\.ssh\allowed_signers" | Out-Null
$pubkey = Get-Content "$env:USERPROFILE\.ssh\id_ed25519_sk_<your-username>-signing.pub"
Add-Content "$env:USERPROFILE\.ssh\allowed_signers" "<your-email> $pubkey"
git config gpg.ssh.allowedSignersFile "$env:USERPROFILE\.ssh\allowed_signers"Go to GitHub → Settings → SSH and GPG keys → New SSH key, set type to Signing Key, and paste the contents of id_ed25519_sk_<your-username>-signing.pub.
git commit --allow-empty -m "test signing"
git log --show-signature -1The YubiKey has a leftover credential with a null user handle. Fix with either:
Force overwrite (add -O overwrite-resident and -O user=<name> as shown in step 1).
List credentials:
ykman fido credentials listDelete a specific credential by ID:
ykman fido credentials delete <credential-id>Full FIDO2 reset (destructive — deletes ALL FIDO2/WebAuthn credentials):
ykman fido resetInstall ykman if needed:
winget install Yubico.YubiKeyManager