# Native Secure Enclaved backed ssh keys on MacOS

> Source: <https://gist.github.com/arianvp/5f59f1783e3eaf1a2d4cd8e952bb4acf>
> Published: 2025-11-23 17:53:28+00:00

# Native Secure Enclave backed ssh keys on MacOS 

It turns out that MacOS Tahoe can generate and use secure-enclave backed SSH keys! This replaces projects like https://github.com/maxgoedjen/secretive

There is a shared library `/usr/lib/ssh-keychain.dylib` that traditionally has been used to add smartcard support
to ssh by implementing `PKCS11Provider` interface. However since recently it also implements `SecurityKeyProivder`
which supports loading keys directly from the secure enclave! `SecurityKeyProvider` is what is normally used to talk to FIDO2 devices (e.g. `libfido2` can be used to talk to your Yubikey). However you can now use it to talk to your Secure Enclave instead!



https://gist.github.com/user-attachments/assets/ff033694-13e1-454e-b42b-b5c19e0fb2a0


Seems this method was first discovered in https://lists.mindrot.org/pipermail/openssh-unix-dev/2024-July/041451.html

## Key setup

See `man sc_auth` and `man ssh-keychain` for all the options

To create a Secure Enclave backed key that requires biometrics, run the
following command and press TouchID:
```
% sc_auth create-ctk-identity -l ssh -k p-256-ne -t bio
```

You can confirm that the key was create with the `list-ctk-identities` command:
```
arian@Mac ssh-keychain % sc_auth  list-ctk-identities       
Key Type Public Key Hash                          Prot Label Common Name Email Address Valid To        Valid 
p-256-ne A71277F0BC5825A7B3576D014F31282A866EF3BC bio  ssh   ssh                       23.11.26, 17:09 YES
```


It also supports listing the ssh key fingerprints instead:
```
% sc_auth  list-ctk-identities -t ssh
Key Type Public Key Hash                                    Prot Label Common Name Email Address Valid To        Valid 
p-256-ne SHA256:vs4ByYo+T9M3V8iiDYONMSvx2k5Fj2ujVBWt1j6yzis bio  ssh   ssh                       23.11.26, 17:09 YES 
```

Keys can be deleted with
```
% sc_auth delete-ctk-identity -h <Public Key Hash>
```


## Usage with `ssh`

You can "download" the public / private keypair from the secure enclave using the following command:
```
% ssh-keygen -w /usr/lib/ssh-keychain.dylib -K -N ""
Enter PIN for authenticator: 
You may need to touch your authenticator to authorize key download.
Saved ECDSA-SK key to id_ecdsa_sk_rk
% cat id_ecdsa_sk_rk.pub 
sk-ecdsa-sha2-nistp256@openssh.com AAAAInNrLWVjZHNhLXNoYTItbmlzdHAyNTZAb3BlbnNzaC5jb20AAAAIbmlzdHAyNTYAAABBBKiHAiAZhcsZ95n85dkNGs9GnbDt0aNOia2gnuknYV2wKL3y0u+d3QrE9cFkmWXIymHZMglL+uJA+6mShY8SeykAAAAEc3NoOg== ssh:
```

You can just use the empty string for PIN. For some reason `openssh` always asks for
it even if the authenticator in question does not use a PIN but a biometric.
Note that the "private" key here is just a reference to the FIDO credential. It does
not contain any secret key material. Hence I'm specifiyng `-N ""` to skip an encryption
passphrase.

Now if you copy this public key to your authorized keys file, it should work!

```
% ssh-copy-id -i id_ecdsa_sk_rk localhost
% ssh -o SecurityKeyProvider=/usr/lib/ssh-keychain.dylib localhost
```


## Usage with `ssh-agent`

Instead of downloading the public/private keypair to a file you can also directly
make the keys available to `ssh-agent`. For this you can use the following command:
```
% ssh-add -K -S /usr/lib/ssh-keychain.dylib
Enter PIN for authenticator: 
Resident identity added: ECDSA-SK SHA256:vs4ByYo+T9M3V8iiDYONMSvx2k5Fj2ujVBWt1j6yzis
% ssh-add -L
sk-ecdsa-sha2-nistp256@openssh.com AAAAInNrLWVjZHNhLXNoYTItbmlzdHAyNTZAb3BlbnNzaC5jb20AAAAIbmlzdHAyNTYAAABBBKiHAiAZhcsZ95n85dkNGs9GnbDt0aNOia2gnuknYV2wKL3y0u+d3QrE9cFkmWXIymHZMglL+uJA+6mShY8SeykAAAAEc3NoOg== 
% ssh-copy-id localhost
% ssh -o SecurityKeyProvider=/usr/lib/ssh-keychain.dylib localhost
```


## Using the SecurityKeyProvider by default

`SecurityKeyProvider` can be configured in `.ssh/config` but I recommend setting
`export SSH_SK_PROVIDER=/usr/lib/ssh-keychain.dylib` in your `.zprofile` instead as
that environment variable gets picked up by `ssh`, `ssh-add` and `ssh-keygen`.

This means you can just do:

```
ssh-add -K
ssh my-server
```

or

```
ssh-keygen -K
ssh -i id_ecdsa_rk_sk my-server
```

to ssh into your server


## Exportable keys

There's also an exportable variant where the private key is encrypted using the secure enclave as opposed to generated on the secure enclave. This is might be considered less secure but is convenient for key backup.

````
% sc_auth create-ctk-identity -l ssh-exportable -k p-256 -t bio
% sc_auth list-ctk-identities
p-256    A581E5404ED157C4C73FFDBDFC1339E0D873FCAE bio  ssh-exportable ssh-exportable               23.11.26, 19:50 YES  
% sc_auth export-ctk-identity -h A581E5404ED157C4C73FFDBDFC1339E0D873FCAE -f ssh-exportable.pem
Enter a password which will be used to protect the exported items:
Verify password:
````

You can then re-import it on another device

```
% sc_auth import-ctk-identities -f ssh-exportable.pem.p12 -t bio
Enter PKCS12 file password:
```


