Keychain Support

Ghostunnel can load certificates and private keys directly from the macOS Keychain or Windows Certificate Store. This lets you use Secure Enclave-backed keys on Touch ID MacBooks, hardware-backed keys via CNG on Windows, or simply manage certificates through the OS instead of as files on disk.

Prerequisites: Creating a PKCS#12 Bundle

Both macOS and Windows import certificates from PKCS#12 (.p12 / .pfx) files. If you have a PEM certificate and key, bundle them first:

openssl pkcs12 -export \
    -in server-cert.pem \
    -inkey server-key.pem \
    -out server.p12 \
    -passout pass:<password>

If you also need to include intermediate CA certificates in the bundle, add -certfile intermediate-ca.pem.

macOS

Importing into the Keychain

Using the CLI (recommended for automation):

security import server.p12 \
    -k ~/Library/Keychains/login.keychain-db \
    -f pkcs12 \
    -P <password> \
    -A

The -A flag allows all applications to access the imported key without a confirmation prompt. Omit it if you prefer per-application access control.

You can also double-click the .p12 file in Finder or use the Keychain Access app to import through the GUI.

Verify the import succeeded:

security find-identity -v

This lists all identities (certificate + private key pairs) in your keychain search list. Look for your certificate’s Common Name in the output.

See also Apple’s Keychain Services documentation and TN3137: On Mac keychain APIs and implementations.

Secure Enclave and Hardware Tokens

On Touch ID MacBooks, private keys can live in the Secure Enclave. Pass --keychain-require-token so Ghostunnel only loads keys backed by a hardware token (e.g. the Secure Enclave or a smart card):

ghostunnel server \
    --keychain-identity <common-name> \
    --keychain-require-token \
    --listen localhost:8443 \
    --target localhost:8080 \
    --cacert cacert.pem \
    --allow-ou=client

This flag is only available on macOS.

See Apple’s Protecting keys with the Secure Enclave and the Secure Enclave security overview for more on hardware-backed keys.

Windows

Importing into the Certificate Store

Using certutil (recommended for automation):

certutil -f -p <password> -user -importpfx MY server.p12

This imports the certificate and private key into the current user’s “MY” (Personal) store. The -user flag targets the current user context. To import into the Local Machine store instead, omit -user (and run as administrator).

Using PowerShell:

Import-PfxCertificate -FilePath server.p12 `
    -CertStoreLocation Cert:\CurrentUser\My `
    -Password (ConvertTo-SecureString -String "<password>" -AsPlainText -Force)

Verify the import:

Get-ChildItem Cert:\CurrentUser\My | Format-Table Subject, Thumbprint, NotAfter

Which stores does Ghostunnel search? When --keychain-identity is used on Windows, Ghostunnel searches three stores in this order:

  1. MY (Current User), the personal certificate store
  2. CURRENT_SERVICE, the current service account’s certificates (if accessible, since v1.8.1)
  3. LOCAL_MACHINE, machine-wide certificates (if accessible; may require elevation, since v1.8.1)

Stores that fail to open are skipped rather than causing an error.

See Microsoft’s certutil reference, System Store Locations, and the Import-PfxCertificate cmdlet docs for more.

Selecting a Certificate

Certificates from the keychain can be selected using one or both of the following flags:

  • --keychain-identity: match by the certificate’s Common Name (CN) or serial number. Ghostunnel collects all certificates where either field matches.
  • --keychain-issuer: match by the issuer’s Common Name (CN).

When both flags are specified, Ghostunnel selects certificates where both attributes match (logical AND). If multiple certificates match, the one with the latest expiration date (NotAfter) is used.

Usage Examples

macOS

Load an identity from the login keychain by subject name:

ghostunnel client \
    --keychain-identity <common-name-or-serial> \
    --listen unix:/path/to/unix/socket \
    --target example.com:443 \
    --cacert cacert.pem

Or filter by issuer name:

ghostunnel client \
    --keychain-issuer <issuer-common-name> \
    --listen unix:/path/to/unix/socket \
    --target example.com:443 \
    --cacert cacert.pem

Windows

On Windows, --keychain-identity and --keychain-issuer work the same way but search the Windows Certificate Store (MY, CURRENT_SERVICE, and LOCAL_MACHINE stores, as described above):

ghostunnel client \
    --keychain-identity <common-name-or-serial> \
    --listen localhost:8080 \
    --target example.com:443 \
    --cacert cacert.pem

Certificate Reloading

Keychain certificates support reloading via SIGHUP/SIGUSR1 (Unix only) or --timed-reload (all platforms). On reload, Ghostunnel re-queries the keychain for a certificate matching the same identity/issuer criteria. If the certificate has been updated in the keychain (e.g. renewed), the new certificate will be used for subsequent connections.

Removing Certificates

macOS: remove an identity (certificate + private key) by Common Name:

security delete-identity -c <common-name>

Or use the Keychain Access app to find and delete the certificate in the GUI.

Windows: remove via PowerShell:

Get-ChildItem Cert:\CurrentUser\My |
    Where-Object { $_.Subject -match "CN=<common-name>" } |
    Remove-Item -DeleteKey

The -DeleteKey flag also removes the private key. You can alternatively use certutil -delstore MY <serial-or-thumbprint>.

Troubleshooting

macOS: certificate not found

  • Check the keychain search list: security list-keychains
  • Unlock the keychain if locked: security unlock-keychain
  • List available identities: security find-identity -v
  • Make sure the CN or serial matches what you passed to --keychain-identity

Windows: certificate not found

  • List certs in the store: Get-ChildItem Cert:\CurrentUser\My
  • If using the Local Machine store, make sure Ghostunnel runs with sufficient permissions
  • Make sure the CN or serial matches what you passed to --keychain-identity

Access denied / permission errors

  • macOS: the keychain may prompt for access. Use -A during import to allow all apps, or grant access to Ghostunnel specifically in Keychain Access.
  • Windows: the account running Ghostunnel needs read access to the private key. You can manage private key permissions through the Certificates MMC snap-in (right-click a certificate, then “All Tasks > Manage Private Keys”).