This article explains how to use a certificate stored on a YubiKey for code signing and signature verification on macOS.
Table of Contents
Finding the YubiKey Manager (CLI) on macOS
Exporting the certificate and public key
Adding certificates to the macOS Keychain
Signing a test program with Codesign
Prerequisites
- YubiKey with a PIV certificate (slot 9a, 9c, or 9d)
- YubiKey Manager (CLI)
- OpenSSL and shasum (standard on macOS)
- Root and intermediate CA certificates from your CA
- Xcode 13 or later (if signing from Xcode)
-
OpenSC installed
Finding the YubiKey Manager (CLI) on macOS
If you installed YubiKey Manager (CLI) using the .dmg file, the ykman command-line tool is inside the app bundle. Its path is
/Applications/YubiKey Manager.app/Contents/MacOS/ykman
You can invoke it directly
"/Applications/YubiKey Manager.app/Contents/MacOS/ykman" piv certificates export 9c yubikey-cert.pem
For convenience, you can add an alias to your shell config (e.g., ~/.zshrc or ~/.bash_profile)
alias ykman="/Applications/YubiKey Manager.app/Contents/MacOS/ykman"
After adding, restart your terminal or run source ~/.zshrc (or source ~/.bash_profile) to use ykman as a command everywhere.
Exporting the certificate and public key
Export your certificate from YubiKey (slot 9c as example)
"/Applications/YubiKey Manager.app/Contents/MacOS/ykman" piv certificates export 9c yubikey-cert.pem
(or just ykman piv certificates export 9c yubikey-cert.pem if you set up the alias)
Extract the public key (for OpenSSL verification)
openssl x509 -in yubikey-cert.pem -pubkey -noout > pubkey.pem
Verifying code signing EKU
macOS requires the certificate to include the "code signing" extended key usage (EKU).
Check EKU with OpenSSL
openssl x509 -in yubikey-cert.pem -text -noout | grep -A 1 "Extended Key Usage"
- You must see code signing in the output
- If missing, request a new certificate from your CA with the correct EKU
Adding certificates to the macOS Keychain
Import your YubiKey certificate
security add-trusted-cert -k ~/Library/Keychains/login.keychain-db yubikey-cert.pem
Import the root and intermediate CA certificates
security add-trusted-cert -k ~/Library/Keychains/login.keychain-db root-ca.pem
security add-trusted-cert -k ~/Library/Keychains/login.keychain-db intermediate-ca.pem
Certificates must be in PEM (.pem) or DER (.cer) format.
Signing a test program with Codesign
Before integrating with Xcode, you should confirm you can sign with your YubiKey on the command line.
Create a test program
Here the built-in true command is used for testing
cp /usr/bin/true true_test
Find the SHA1 hash of your certificate
Get the fingerprint
openssl x509 -in yubikey-cert.pem -noout -fingerprint -sha1
Example output
SHA1 Fingerprint=E1:B8:B2:0E:47:F1:D4:AE:9A:65:30:8C:1F:50:E7:A4:B6:E0:F7:C2
make sure to remove the colons between each digit pair.
Sign the program
codesign -s E1B8B20E47F1D4AE9A65308C1F50E7A4B6E0F7C2 -f "true_test"
- Replace the hash with your actual certificate’s SHA1
- The -f flag forces replacing any existing signature
- When prompted, enter your YubiKey PIN
Example output:
true_test: replacing existing signature
Signing from Xcode
Open your project in Xcode
- Create a new project or open an existing one (e.g., File > New > macOS > Command Line Tool).
Configure signing
- Go to Signing & Capabilities for your tool target
- Turn off Automatically manage signing
- In Build Settings, find the Code Signing Identity setting, choose Other, and enter the SHA1 hash of your YubiKey certificate
Build
- Choose Product > Build
- When prompted for the PIN, enter it and approve on your YubiKey
Warning: Xcode 13 or later is required for direct signing using a token-based (YubiKey) identity. Earlier Xcode versions only support file-based identities, not hardware tokens.
Verifying signatures
Verify a macOS application's signature
codesign --verify --deep --strict --verbose=2 /path/to/MyApp.app
View certificate details in a signed application
codesign -d --verbose=4 /path/to/MyApp.app
- Look for Authority= and SHA-1 hash=
-
These should match your Common Name and SHA1 hash of the certificate on your YubiKey
Troubleshooting
Codesign fails or app is not trusted
-
-
-
- Ensure your YubiKey certificate and all CAs are in the login keychain and trusted
- Confirm the certificate includes the Code Signing EKU
- Ensure your YubiKey certificate and all CAs are in the login keychain and trusted
-
-
OpenSSL verification fails
-
-
-
-
- Check that the public key matches the private key used for signing
- Check that the public key matches the private key used for signing
-
-
-
Quick reference table
Task | Command Example |
Export YubiKey cert | ykman piv certificates export 9c yubikey-cert.pem |
Extract public key | openssl x509 -in yubikey-cert.pem -pubkey -noout > pubkey.pem |
Check EKU for code signing | openssl x509 -in yubikey-cert.pem -text -noout | grep -A 1 "Extended Key Usage" |
Import public key cert to keychain | security add-trusted-cert -k ~/Library/Keychains/login.keychain-db yubikey-cert.pem |
Import root/intermediate to keychain | security add-trusted-cert -k ~/Library/Keychains/login.keychain-db root-ca.pem |
Sign program with YubiKey | codesign -s <SHA1_HASH> -f "MyApp" |
Verify macOS application signature | codesign --verify --deep --strict --verbose=2 /path/to/MyApp.app |
View signing cert in app | codesign -d --verbose=4 /path/to/MyApp.app |
Additional notes
- The certificate must include the code signing EKU (OID: 1.3.6.1.5.5.7.3.3)
- Xcode 13+ is required to use token-based identities for signing
- All CA certificates (root and intermediates) must be present and trusted in your Keychain for macOS to trust your signatures