Setting up SSH keys on macOS with Touch ID
本文为原文前 6,000 字符的节选翻译,完整内容请查看原文。
Setting up SSH keys on macOS with Touch ID
在 macOS 上设置带有触控 ID (Touch ID) 的 SSH 密钥
October 19, 2026 2026 年 10 月 19 日
In the first part of this post I’ll show a simple, secure way to create an SSH key on Mac (it’s 3 commands, including support for GitHub). In the second part I’ll dig deeper and explain what’s actually happening for the curious reader. 在这篇文章的第一部分,我将展示一种在 Mac 上创建 SSH 密钥的简单且安全的方法(只需 3 条命令,包括对 GitHub 的支持)。在第二部分,我将深入探讨并为好奇的读者解释其背后的原理。
Macs have a built-in so-called Secure Enclave, where we can create “identities” that simply cannot be stolen (unless maybe you’ve made enemies with a nation state). Those identities are protected with Touch ID and can be used for SSH authentication. Mac 内置了所谓的“安全隔区”(Secure Enclave),我们可以在其中创建根本无法被窃取的“身份”(除非你得罪了某个国家级势力)。这些身份受触控 ID 保护,并可用于 SSH 身份验证。
There are some great benefits about using this over traditional SSH key files: The private material cannot be extracted, is never shown, cannot be stolen, You get prompted whenever the identity is used, No key files (like ~/.ssh/id_ed25519.pub and friends) littering the file system; and there’s no risk of mistakenly deleting them either. 与传统的 SSH 密钥文件相比,使用这种方法有许多显著优势:私钥材料无法被提取、从不显示、无法被窃取;每次使用身份时都会收到提示;文件系统中不会有杂乱的密钥文件(如 ~/.ssh/id_ed25519.pub 等);也不存在误删的风险。
This extra security will be in effect whenever you use SSH, including git-over-ssh like GitHub. It’s great that advanced security tech is available by default on some of the most widely distributed computers in the world! A few years ago stuff like this could only be found at CERN and/or in Dan Brown novels. Let’s see how it can be set up on your consumer-grade Mac. 这种额外的安全性在你使用 SSH 时都会生效,包括像 GitHub 这样的 git-over-ssh 操作。令人高兴的是,世界上分布最广的一些计算机默认就配备了这种先进的安全技术!几年前,这类东西还只能在欧洲核子研究中心 (CERN) 或丹·布朗的小说中见到。让我们看看如何在你的消费级 Mac 上进行设置。
“It is essential that the human interface be designed for ease of use, so that users routinely and automatically apply the protection mechanisms correctly.” — Saltzer and Schroeder, “The Protection of Information in Computer Systems” “人机界面的设计必须易于使用,以便用户能够常规且自动地正确应用保护机制。”——萨尔策 (Saltzer) 和施罗德 (Schroeder) 合著的《计算机系统中的信息保护》
Quick Setup 快速设置
We’ll create a secure identity on the Secure Enclave, then tell SSH how to use it for authentication, and finally add the key to GitHub. 我们将会在安全隔区上创建一个安全身份,然后告诉 SSH 如何使用它进行身份验证,最后将密钥添加到 GitHub。
Step 1: create the identity that you’ll use on this Mac: 第一步:创建你将在这台 Mac 上使用的身份:
sc_auth create-ctk-identity -l ssh-key -k p-256-ne -t bio # run once to create identity
sc_auth create-ctk-identity -l ssh-key -k p-256-ne -t bio # 运行一次以创建身份
You’ll be prompted to touch “Touch ID”. Your identity is now created and saved securely (parameters are explained in the deep dive below). 系统会提示你触摸“触控 ID”。你的身份现已创建并安全保存(参数将在下文的深入探讨中解释)。
Step 2: tell SSH to use the identity (when prompted for a PIN, just hit enter): 第二步:告诉 SSH 使用该身份(当提示输入 PIN 码时,直接按回车即可):
ssh-add -K -S /usr/lib/ssh-keychain.dylib # run after a reboot
ssh-add -K -S /usr/lib/ssh-keychain.dylib # 重启后运行
From here on, SSH will know to use the identity from the Secure Enclave when connecting via SSH; it does not have a good memory so you’ll need to remind it after a reboot. 从现在起,SSH 在通过 SSH 连接时将知道使用来自安全隔区的身份;由于它的记忆力不太好,你需要在重启后提醒它。
Step 3: Whenever you need to register your key to a new server (like GitHub), run this command: 第三步:每当你需要将密钥注册到新服务器(如 GitHub)时,运行此命令:
ssh-add -L # run when you need the public key
ssh-add -L # 在需要公钥时运行
If multiple identities are listed, use the line that starts with sk-ecdsa-sha2-nistp256… It’s a shareable handle for the identity, and this is the SSH key that GitHub will ask about. The output of ssh-add -L can be added as a GitHub SSH Key. 如果列出了多个身份,请使用以 sk-ecdsa-sha2-nistp256… 开头的那一行。这是该身份的可共享句柄,也是 GitHub 会要求的 SSH 密钥。ssh-add -L 的输出可以添加为 GitHub SSH 密钥。
That’s all you need for a super secure setup! The new identity can now be used with SSH, and you’ll be prompted for Touch ID during authentication: 这就是实现超安全设置所需的全部内容!新身份现在可以与 SSH 一起使用,并且在身份验证期间会提示你使用触控 ID:
git push # triggers Touch ID prompt
git push # 触发触控 ID 提示
No one can steal your identity (well, you can’t even give it away willingly since it can’t be extracted from the Secure Enclave), but with great powers etc: if your Mac dies, so does the identity, and you’ll need to create a new one (and re-register it where necessary, like GitHub). 没有人能窃取你的身份(好吧,即使你自愿想给别人也做不到,因为它无法从安全隔区中提取出来),但能力越大责任越大:如果你的 Mac 坏了,身份也会随之消失,你需要创建一个新的(并在必要的地方重新注册,例如 GitHub)。
You’ll get a Touch ID prompt when git tries to authenticate with SSH. If you’re curious about how this works, read on! 当 git 尝试通过 SSH 进行身份验证时,你会收到触控 ID 提示。如果你对它的工作原理感到好奇,请继续阅读!
Under the hood 幕后原理
We’ll now try to understand what happens under the hood. We’ll start with the actual identity creation in the Secure Enclave, then look at how SSH is allowed to interface with the Secure Enclave with ssh-keychain.dylib, and then try to see what happens in a complete SSH sign-in flow. 现在我们尝试了解幕后发生了什么。我们将从安全隔区中实际的身份创建开始,然后看看 SSH 是如何通过 ssh-keychain.dylib 与安全隔区进行交互的,最后看看完整的 SSH 登录流程中发生了什么。
This is the result of reading posts (like this great investigation by arianvp), manual pages, and experimentation. A lot of this is undocumented, and this is the minimum information I needed to form a mental model of what’s happening and convince myself that it does, indeed, work. 这是阅读文章(如 arianvp 的这项出色调查)、手册页和实验的结果。其中许多内容没有文档记录,这是我形成心理模型并确信它确实有效所需的最少信息。
Note: Some of the command outputs below have been trimmed for legibility, I invite you to run them locally if you want the full experience! 注意:为了清晰起见,下面的一些命令输出已被删减,如果你想获得完整体验,欢迎在本地运行它们!
Creating an identity on the Secure Enclave 在安全隔区上创建身份
Identities are managed with the sc_auth command (where sc_ stands for Smart Card). In Apple-speak, they are “CryptoTokenKit” identities, or CTK identities for short. Why not Smart Card Identities? What is a Smart Card? No idea! There’s a lot of weird Apple vocabulary, but in practice they’re just private keys stored on the Secure Enclave: 身份通过 sc_auth 命令进行管理(其中 sc_ 代表智能卡)。在苹果的术语中,它们被称为“CryptoTokenKit”身份,简称 CTK 身份。为什么不叫智能卡身份?什么是智能卡?不知道!苹果有很多奇怪的词汇,但实际上它们只是存储在安全隔区上的私钥:
$ sc_auth list-ctk-identities
Key Type Public Key Hash Prot Label
p-256-ne 458F712F281B53C683F23FC02E69D44DAFDAA3DE bio ssh-key
If you followed along in the Quick Setup, you should have exactly one identity here, that was created when you ran the sc_auth create-ctk-identity command. Let’s look at the create-ctk-identity command in more detail: 如果你按照“快速设置”操作,这里应该只有一个身份,即你在运行 sc_auth create-ctk-identity 命令时创建的那个。让我们更详细地看看 create-ctk-identity 命令:
sc_auth create-ctk-identity -l <label> -k <key type> -t <protection>
sc_auth create-ctk-identity -l <标签> -k <密钥类型> -t <保护方式>
When using the p-256-ne key type, this command creates the identity on the Secure Enclave — I’m guessing by first gathering some entropy, then generating some private key material and allocating whatever it needs for bookkeeping and ensuring it can only be accessed with your fingerprint. 当使用 p-256-ne 密钥类型时,此命令会在安全隔区上创建身份——我猜它是通过首先收集一些熵,然后生成一些私钥材料,并分配其簿记所需的一切,同时确保它只能通过你的指纹访问。
The label is freeform and just a note attached to the key. The key type is a cryptographic setting (the elliptic curve used). At the time of writing, the following values are accepted: p-256|p-384|p-521|p-256-ne|p-384-ne. 标签是自由格式的,只是附加在密钥上的一个注释。密钥类型是一种加密设置(所使用的椭圆曲线)。在撰写本文时,接受以下值:p-256|p-384|p-521|p-256-ne|p-384-ne。
The -ne suffix means “Non-Extractable”, meaning the key is generated by the enclave itself and cannot be extracted from the Secure Enclave. For SSH we only need signing, which is done by (and on) the Secure Enclave itself, and at no point do we need (or want) to export the private key. -ne 后缀表示“不可提取”,意味着密钥由隔区本身生成,且无法从安全隔区中提取。对于 SSH,我们只需要签名,这由安全隔区本身(并在其内部)完成,我们不需要(也不希望)在任何时候导出私钥。
The p-384 curve is not supported by (Open)SSH, so this narrows it down to p-256-ne. Finally, protection can be either bio or none. When set to bio, using the key requires biometrics (like Touch ID). With none, the key still cannot be extracted (i.e. stolen) but programs would be able to silently use SSH; I recommend using bio, but YMWV; if you get annoyed by the Touch ID prompts whenever you git pull, you might want to use none here. (Open)SSH 不支持 p-384 曲线,因此范围缩小到 p-256-ne。最后,保护方式可以是 bio 或 none。设置为 bio 时,使用密钥需要生物识别(如触控 ID)。设置为 none 时,密钥仍然无法被提取(即被窃取),但程序将能够静默使用 SSH;我建议使用 bio,但情况因人而异;如果你对每次 git pull 时出现的触控 ID 提示感到厌烦,你可能想在这里使用 none。
Now that we have some elusive identity on 现在我们有了一些难以捉摸的身份在……