Using YubiKeys with Xcode and Codesign


 

This article explains how to use a certificate stored on a YubiKey for code signing and signature verification on macOS.

 

Table of Contents

Prerequisites

Finding the YubiKey Manager (CLI) on macOS

Exporting the certificate and public key

Verifying code signing EKU

Adding certificates to the macOS Keychain

Signing a test program with Codesign

Signing from Xcode

Verifying signatures

Troubleshooting

Quick reference table

Additional notes

 

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

  1. Go to Signing & Capabilities for your tool target
     
  2. Turn off Automatically manage signing
     
  3. 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
       
exclamation-triangle-line-icon.svg 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

OpenSSL verification fails

          • 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