What is a YubiKey?
A YubiKey is a small hardware device used as a second factor of authentication. It works similarly to one-time codes sent by SMS or email - but much more securely. To authenticate, the YubiKey must be physically inserted into your computer or connected via NFC. This makes it nearly impossible for remote attackers to compromise your credentials.
Getting a YubiKey
The best place to buy a YubiKey is directly from Yubico . You can also buy them from trusted retailers, but always verify the device is genuine using Yubico’s verification page .
It’s recommended to have at least two YubiKeys as a backup in case you lose or damage the primary device.
Initial Setup
First, install YubiKey Manager and change the default PINs and management keys. Here is a good guide about that: Changing the default management key and PIN
Other Prerequisites
Since, we want to use the YubiKey for SSH authentication and Git signing, install these tools:
brew install gnupg ykman pinentry-mac
GPG Interface
The GPG (OpenPGP) interface on the YubiKey uses two separate PINs:
- Admin PIN: required when loading GPG keys to the YubiKey. Default: 12345678
- User PIN: used when signing, encrypting, or authenticating. Default: 123456
You can change them using:
ykman openpgp access change-admin-pin
ykman openpgp access change-pin
By default, the YubiKey automatically approves signing and encryption requests when inserted. For extra security, I recommend enabling touch confirmation:
ykman openpgp keys set-touch aut off
ykman openpgp keys set-touch sig on
ykman openpgp keys set-touch enc on
Create GPG Keys and Upload to YubiKey
Create a temporary directory which will be cleared on reboot and set it as the GnuPG directory:
export GNUPGHOME=$(mktemp -d -t $(date +%Y.%m.%d)-XXXX)
cd $GNUPGHOME
Generate a new GPG key:
gpg --expert --full-generate-key
Choose:
9 - ECC sign & encrypt
Curve 25519
Does not expire
Choose a strong but memorable password
The password you set here is your GPG Key Password.
Export the Key ID
List your keys and note the Key ID:
gpg --list-secret-keys --keyid-format=long
Example output:
sec> ed25519/E965C2667A7373F1 2025-11-05 [SC]
F510240484630D8494F7EF10E965C2667A7373F1
uid [ultimate] Your Name (Comment) <[email protected]>
ssb> cv25519/C00CCD4A3EACEA9E 2025-11-05 [E]
The Key ID is E965C2667A7373F1.
export KEY_ID="E965C2667A7373F1"
Adding Additional Identities
If you want to use the same key for multiple email addresses:
gpg --expert --edit-key $KEY_ID
> adduid
Follow the prompts and type save when done.
Changing Expiration and Creating Subkeys
Let’s change expiration for encryption key:
gpg --expert --edit-key $KEY_ID
> key 1
> expire
Choose:
Key is valid for? (0) 2y
Is this correct? (y/N) y
save
Create signing subkey:
gpg --expert --edit-key $KEY_ID
> addkey
Choose:
(11) ECC (set your own capabilities)
(Q) Finished
(1) Curve 25519 _default_
2y
Create authentication subkey:
gpg --expert --edit-key $KEY_ID
> addkey
Choose:
(11) ECC (set your own capabilities)
(S) Toggle the sign capability
(A) Toggle the authenticate capability
(Q) Finished
(1) Curve 25519 _default_
2y
save and quit.
Exporting Keys
The primary key is responsible for issuing Subkeys for encryption, signature and authentication operations. The primary key should be kept offline at all times and only accessed from a dedicated and secure environment to issue or revoke Subkeys.
gpg --armor --export-secret-keys $KEY_ID > primary.key
gpg --armor --export-secret-subkeys $KEY_ID > sub.key
gpg --armor --export $KEY_ID > public.key
echo $KEY_ID > key_id
Create an encrypted/password protected archive and store it in a secure location.
Copy public key to a key registry
Go to https://keys.openpgp.org and upload your public key and verify the email.
This service we will be using later to import the public key.
Uploading Keys to YubiKey
gpg --expert --edit-key $KEY_ID
> key 1
> keytocard
Choose (2) Encryption key and answer the password/PIN prompts as before. Next:
> key 1
> key 2
> keytocard
Choose (1) Signature key, it’ll prompt for the GPG Password, then it’ll ask for the GPG Admin PIN. Next:
> key 2
> key 3
> keytocard
Choose (3) Authentication key and passwords/PINs again.
save and quit.
If you want to configure additional yubikey, you need to restore GPG keys from the backup, import them and repeat the process of uploading to the new yubikey.
Git Signing Configuration
Configure Git to sign commits automatically:
git config --global user.signingkey $KEY_ID
git config --global commit.gpgsign true
Export your public key and add it to GitHub or GitLab:
gpg --armor --export $KEY_ID | pbcopy
And paste the value into your GitHub/Gitlab settings.
SSH Configuration
Export your public key in SSH format:
gpg --export-ssh-key $KEY_ID
Add it to your remote services (GitHub, GitLab, Bitbucket, etc.).
Configure GPG Agent
Create or edit ~/.gnupg/gpg-agent.conf:
enable-ssh-support
pinentry-program /opt/homebrew/bin/pinentry-mac
Restart the agent:
gpg-connect-agent updatestartuptty /bye > /dev/null
And add this to ~/.ssh/config:
Host *
IdentityAgent ~/.gnupg/S.gpg-agent.ssh
Switching Between Keys
If you use multiple YubiKeys, GPG needs to refresh the active key.
Add this helper function to your .zshrc or .bashrc:
function switchyubi() {
rm -r ~/.gnupg/private-keys-v1.d
gpgconf --kill gpg-agent
gpg --card-status
}
Run switchyubi after plugging in your YubiKey to reload the correct key.
Testing
Open a new terminal/session and run
export KEY_ID=965C2667A7373F1 # Replace with your KEY_ID
gpg --keyserver hkps://keys.openpgp.org --recv-keys $KEY_ID
switchyubi
> gpg --list-keys --keyid-format=long
[keyboxd]
---------
pub ed25519/E965C2667A7373F1 2025-11-05 [SC]
F510240484630D8494F7EF10E965C2667A7373F1
uid [ultimate] Your Name (Comment) <[email protected]>
ssb> cv25519/C00CCD4A3EACEA9E 2025-11-05 [E] [expires: 2027-11-05]
sub> ed25519/7A3EACEA9EDF123D 2025-11-05 [S] [expires: 2027-11-05]
sub> ed25519/ACEA9E2342DDE33C 2025-11-05 [A] [expires: 2027-11-05]
Conclusion
Using a YubiKey for SSH and Git signing adds a strong security layer without sacrificing convenience. It is a great step toward securing your workflow and protecting your digital identity.
