r/programming • • 7d ago

SSH keys on macOS with Touch ID

https://nmattia.com/posts/2026-10-19-setting-up-ssh-keys-touch-id/

I've recently discovered that you can use Touch ID (rather, the Mac's Secure Enclave) for SSH authentication. I'm the author of the post, feel free to ask any questions and if there are any experts I'd love to hear your thoughts!

441 Upvotes

51 comments sorted by

147

u/odlp 7d ago

Very cool. Thanks for the write up, had no idea this was possible.

Currently use the 1Password SSH agent which offers similar benefits like no keys on disk, TouchID authorization:

https://1password.com/developers/ssh

18

u/nmattia 7d ago

Ah, very nice. I only became aware of the 1Password integration a few minutes ago! So 1Password acts like a key provider, is that right?

7

u/kisielk 7d ago

Yes it has its own ssh agent

1

u/atheken 6d ago

Yes, and it works very well

35

u/cbarrick 7d ago

But this is just like any other SSH agent: once decrypted the key is stored in memory.

IIUC, in the OP, the key is stored on the secure enclave and is never put in memory.

So it is secure against malware that can read your memory or that compromise your SSH agent. (Though if that happens, you probably have bigger fish to fry.)

21

u/oscooter 7d ago

> But this is just like any other SSH agent: once decrypted the key is stored in memory.

You are correct, but 1Password does put some care into it to ensure your key is only loaded into memory for the duration it is actually needed. Not completely invulnerable to compromise, but only so much you can do if your key isn't backed by a separate piece of hardware like you mention 

3

u/boots_n_cats 7d ago

Bitwarden also has this feature. Life changing when I figured out it existed.

5

u/iamapizza 7d ago

Similarly been using keepassxc for this, IMO a password vault should be open source and not behind a paywall so 1password doesn't make sense in my threat modelling.

4

u/stemaho 7d ago

Agree and keepassxc can do this as well (at least on a Mac). It talks to your ssh provider and does not bring an own ssh implementation
So just as it should be

1

u/rursache 7d ago

i have the same setup and it's awesome

35

u/rzwitserloot 7d ago

Secretive.app is a small open source roll that nices this process up for you, and allows skipping the touch id step too, I'd you prefer.

10

u/nmattia 7d ago

Yup, came across it! I prefer to avoid relying on 3rd party tools but I read some good things about Secretive while researching this. Note that in the second part of the article I touch (pun intended) on using the Secure Enclave without Touch ID, you might be interested (though I haven't tried it myself)

-2

u/DemonWav 7d ago

I like the concept, but not being able to export the keys is an unfortunate deal breaker for me.

4

u/UnreasonableSteve 7d ago

That's literally the whole selling point of the secure enclave...

3

u/rzwitserloot 7d ago

If you can export the key, then the entire exercise is completely useless.

The point of a key stored in the secure enclave is that you cannot get it out. Here are things that the SE can protect you against that very few other security systems can ever protect you against:

  • Someone steals my laptop. It is locked when it was stolen. A hacker with some capability (such as memory stick readers and the like) gets their hands on it.

  • I leave my laptop unattended and unlocked for a moment. Yes, stupid, but, I did. Some enterprising hacker decides to obtain my private key, and then leaves no trace. They don't steal my laptop. I never realise they've done this.

This SE setup protects against both. If you were able to export the key, it wouldn't protect against the second one, and may not protect against the first.

I'm guessing the fix to what you actually want is simply to have 2 authorized keys. One of them is your secure enclave key (which has, inherently, as part of its multiple factors of protection: Your laptop is REQUIRED to use it. If it is stolen, or broken, then this access path is done, forever. There is no backup, and there is no duplicate). The other one is another key, not a secure enclave based one (or a secure enclave solution on another machine which is rarely or never in the same location as the device hosting the first key).

Think of, for example:

  • A generated key, private key printed out on paper, using a printer you know has no internal caches, generated on a fresh box, delete the key and wipe the disk afterwards or send the public key straight to the printer, or even copy it by hand, then store this piece of paper in a safe or with a notary or similar. This is your backup key, it's unwieldy to use for normal server work.

  • Similar as above but on a USB disk, formatted as FAT32 (easy to read on any system), using simple encryption (such as AES256 with a password you know). USB stick goes in an envelope, and that goes in a safe).

  • 3 separate laptops owned by 3 separate people in 3 separate locations, they can all log in. There's a policy that if any of the 3 is lost or broken, that's an emergency and the other 2 will scramble to verify the identity of the 3rd, while the 3rd buys a new laptop and generates a new key, which the other 2 will then set it up. If all 3 laptops are ever simultaneously lost, there is no way to access that server ever again; they are each other's backups.

Trying to get the maximum security based on a single key is not really possible, you want multiples.

12

u/danemacmillan 7d ago edited 7d ago

Neat! Thanks for this, Nicolas. Learning how to squeeze a bit more out of MacOS and Apple products natively and without third-party tooling is something that always piques my interest.

While reading the article, I kept waiting for the moment you'd explain a bit how this interacts with an existing ~/.ssh/config file. I have a fairly elaborate configuration with a global Host rule at the top, and then more particular rules later on. For example, Host * is configured with multiple IdentityFile entries to support both ed25519 and then a fallback to older rsa identity files for hosts that just cannot support more secure identification.

Is there a way to specify in the config file to use an identity that's in the Secure Enclave? Splitting the rules between an easily scannable config file that also serves the purpose of consolidating remote access, and then a more obscure command-only output approach, in my eyes means that someone will eventually forget how to access, modify, delete, or even recall anything they put in the Secure Enclave, which then lends itself to generating more identities and ultimately loosening up one's security posture. We're all human, after all, and reminding ourselves of that fallibility generally keeps us honest and produces simpler solutions that are easy to maintain and verify.

I think discussing this would really round out an already solid article, and help someone like me be able to jump on this approach piecemeal, while maintaining confidence that months down the road when I next scan the config file I can be reminded of this cool technique that's being used for a given host.

4

u/nmattia 7d ago

Hi Dane,

That's a great question. That's an aspect I did not consider at all; I purposely avoid `~/.ssh/config` because I prefer having as little configuration as possible. My setup is much simpler though, and I mostly use one key per machine.

I *guess* the answer is "no" and you can't reference a Secure Enclave key with IdentityFile directly; that being said, that'll probably depend on the specific implementation. I think Apple's ssh is close enough to OpenSSH, and it's probably worth checking if OpenSSH supports something similar to IdentityFile that supports specifying a key loaded from a provider: https://github.com/mfriedl/openssh/blob/master/sk-api.h

It would be interesting to see what `ssh -i <some secure enclave key>` says; that's not a direct answer to your question but might be a step in the right direction!

Hope you got something out of the article, even if it's not a complete solution for you!

1

u/danemacmillan 7d ago

If no one else does this research, this'll be one of those questions kicking around the back of my mind for an eternity. If I ever get the time to verify this, I'll be sure to update. Similarly, if you ever do, please post an update :)

1

u/nmattia 7d ago

Hah, I know the feeling ;)

3

u/deeelock 7d ago edited 7d ago

I’m not exactly sure, but it sounds similar to 1Password
running as the SSH agent and needing to know how to match SSH keys to servers (to avoid the Too many authentication failures error if you have multiple SSH keys loaded in the agent).

Basically… to get 1Password to know which private key to offer the server, you copy the public key to your ~/.ssh folder and reference it as the `IdentityFile` in your SSH config for that host: https://www.1password.dev/ssh/agent/advanced#match-key-with-host

I’m not sure if 1Password is doing anything specific here for the pubkey identity file to match with the private key in the vault... But maybe this is some standard SSH agent feature that would also work with the Secure Enclave keys (at least for Apple’s version of ssh-agent)?

1

u/thedufer 7d ago

I haven't tried this but I think you should be able to point ssh at your trusted enclave keys with SecurityKeyProvider /usr/lib/ssh-keychain.dylib in your config. It'll probably require touch ID on every ssh in that case (unless you're e.g. re-using connections with ControlMaster), though, whereas the approach described in the article keeps the keys available via your ssh agent.

5

u/tomtennn 7d ago

Nice. That's really awesome that Apple made it that easy.

One major drawback, though: It's SK keys only? That means the server must support it. Sure, a modern OpenSSH will, but will dropbearssh? Will your cisco router? Not like you can "just" buy a replacement for your million dollar router to get a newer SSH.

I use a yubikey with its PKCS#11 support. It's a bit of a hassle provisioning the key, but after that it's just ssh-add -s /usr/lib/x86_64-linux-gnu/opensc-pkcs11.so instead of the similar command from the article, and it's in your ssh-agent. More words here.

Hell, after provisioning, the key even works on Windows!.

I don't suppose the macOS thingy can be used with straight non-SK RSA keys? (I don't have a mac)

3

u/nmattia 7d ago

I did not consider that! My use case is really for GitHub and then maybe a couple of e.g.(recent) Ubuntu boxes. Thanks for the link, I'll have a read.

Regarding the key types, it's only elliptic curves AFAICT (I briefly touch on this here: https://nmattia.com/posts/2026-10-19-setting-up-ssh-keys-touch-id/#creating-an-identity-on-the-secure-enclave). Is that what you meant by "SK"?

3

u/tomtennn 7d ago

No, the SK keys, like I can see in your screenshot when you show part of the output of ssh-add -L, indicate FIDO/U2F keys, which will have a slightly different format than the non-sk ones. It's not clear to me why, except in order for the server to (though not foolproofly) mandate that the client uses a hardware-backed key.

My yubikey solution makes the output of ssh-add -L start with ssh-rsa, which yes is marked legacy RSA/SHA-1, but has the benefit of not requiring server support.

But your use case is like 99% of use cases. It's just a shame when you encounter that 1% and will have to find an alternative solution just for those servers.

Well, to be fair, if you're running a telco/large ISP, it'll likely be WAY more than 1%.

4

u/tj-horner 7d ago

you’ll need to remind it after a reboot

I'm surprised you didn't go into a solution for this! It would get pretty annoying to manually re-run that command after every reboot lol

3

u/nmattia 7d ago

yeah I got a bit frustrated there! the problem is that the command (to be run after a reboot) asks for a PIN; the PIN isn't even used but it means it's not straightforward to add it to e.g. your `.profile` and call it a day. I think a nicer way to go about this is to warp `ssh` in a bash/zsh function which checks if the keys have been loaded yet, and if not summons them. But this is not so different from calling `ssh-add` with regular (file) keys, plus it's with shell history it's pretty fast to re-run the command... but yeah I'm not very happy it either :p

1

u/deviled-tux 5d ago

Mm mine just works, I don’t have to do anything after reboot (I set it up a while back, not specifically using your article but seems similar)

so I guess there’s a way, unfortunately I don’t what the difference is

1

u/nmattia 5d ago

Interesting. Do you have something in `~/.profile` or `/etc/profile` maybe?

3

u/DelusionalPianist 7d ago

Funny that I didn’t know it could be done without 1Password. But that being in the enclave means I have no ability to transfer or backup that key, correct?

4

u/nmattia 7d ago

Yup, that's correct, YMMV but that's a plus for me (even before using the Secure Enclave I used a separate key per machine for fine-grained access control)

2

u/N_T_F_D 7d ago

You're not meant to backup these kinds of keys in order to have the highest assurance of security, you need to have other keys as backups; for instance it's possible to use a Yubikey as your ssh key and it prompts you for the PIN code when you ssh somewhere; you could have the main key in the SE and backups on yubikeys

1

u/3urny 7d ago

Usually for ssh-add you can configure a time for which you won't be asked for the password again. Do you think there's a way to not get asked for the fingerprint for some time here, too? I saw you included the option with no protection at all but it would be nice if there was a middle ground.

1

u/nmattia 7d ago

Mh, that'd be great! I think (with standard key files) ssh-add first unlocks the private key and then keeps it unlocked in memory, which means it can actually use it as much as it wants. With the Secure Enclave key (at least the non extractable ones) the SSH agent actually has to ask the enclave for a signature every time, which in turn will prompt for Touch ID. So I'm assuming there's no way to achieve this from SSH itself, but I'll keep this in mind and report back if I come across something.

1

u/iamthegemfinder 7d ago

Good post, the thought of cleaning out ~/.ssh pleases me, always have found it feels naggingly off somehow to have the key files and stuff just lying around in there. I’ll be setting it up shortly. Presumably it means I can also perform the authentication with my apple watch, as that’s part of the same prompt as touch ID, which is kind of amusing to picture

2

u/nmattia 7d ago

Heh agreed, I always felt uneasy about those keys lying around, even if they're passphrase protected. Regarding the Apple Watch, I'm not sure; some services do manage to share secrets across devices but here I believe it's a little too low level and would need to be implemented as a different security key provider or SSH agent.

1

u/iamthegemfinder 7d ago

Good point, I have no real idea how the watch unlock option is integrated in that sense, I’ll be sure to report back if it does work without fuss

1

u/Carvalho_lukjas 7d ago

pretty cool actually, keeping ssh keys in the secure enclave makes sense, curious how it handles multiple keys tho

4

u/nmattia 7d ago

It works just fine; in the second part ("Under the Hood") I go into a bit more details (though not explicitly about multiple keys). You can run the `create-ctk-identity` command multiple times. When you run `ssh-add -K -S ...`, all keys will be added at once, and then `ssh-add -L` will list all the public keys.

1

u/captain_zavec 7d ago

Oh wow that's super cool! I knew about touch to sudo but I never thought to try and do something like this!

1

u/double-you 7d ago

What's a Smart Card?

If you have a sensible bank, your credit card is one. An ID card can be too.

1

u/lathiat 7d ago

I use secretive for this which also keeps the key in the Secure Enclave: https://secretive.dev/

1

u/Own_Band198 1d ago

very nice, thanks for pointing this app

1

u/romulof 6d ago

1Password for the win

-2

u/First_Inspection_478 7d ago

This is neat, but these days I have agents sshing and it’s annoying for them to be blocked by my touchID.

2

u/nmattia 7d ago

That makes sense; for that use case you might want to disable biometrics protection (see https://nmattia.com/posts/2026-10-19-setting-up-ssh-keys-touch-id/#creating-an-identity-on-the-secure-enclave)

1

u/First_Inspection_478 7d ago

Thanks. Great write up nonetheless. Learned a bunch!

12

u/mkosmo 7d ago

Create them their own keys. I don't want agents using the same keys I do, in case I need to cut them off without cutting myself off.