Passkey通行密钥入门 · 讲义与学习笔记

用公私钥替代密码的登录方式,理解它如何工作以及为什么更安全。

整理:问学·科技

第 1 关 · 密码登录的痛点与风险

看清密码时代留下的安全窟窿,明白为什么业界急着找替代方案

人类设密码的天然缺陷

人类设密码的天然缺陷

你有没有过这种经历:注册新账号时看到「密码不符合要求」,来回试了三次才设上;设完第二天就忘了,又点「忘记密码」重置一次。这不是你的问题——这是整个密码时代留给普通人的结构性困境。要看懂为什么 Passkey 会出现,先得看清这一层。

一、人脑天生就不是「随机数生成器」

我们的工作记忆(短期能稳定记住的信息)一次只能容纳大约 5–7 个独立项。这不是「不努力」,是大脑的硬件限制——心理学家米勒的经典研究早就证实了。

完全随机的字符串,比如 `kJ8#mP2$vL9!`,对人脑来说就是一段「噪声」。它没有意义、没有故事、没有锚点,大脑几乎没办法把它存进长期记忆。所以你设完一定忘,忘了就重置,重置又用一个「好记的」——循环开始。

反过来,大脑是「模式识别机器」。我们天然会去找规律、找意义、找联想。生日、姓名、宠物名、键盘上能划出一条直线的字母(qwerty、asdf)——这些都是大脑「偷懒」的方式,也是攻击者最容易猜的方式。

二、大家实际在用什么密码?

每年 NordPass、SplashData 都会发布全球最常用密码榜单,冠军常客永远是这些:

即使你「没那么离谱」,分析真实泄露数据的研究也反复发现:

这些不是个别人的「懒」,是统计学层面的群体行为。

三、「强密码规则」反而把人逼向更可预测

为了逼用户用强密码,网站过去二十年加了一堆规则:必须 8 位以上、含大小写、含数字、含特殊符号、每 90 天必须改一次、不能和上次重复……

但 NIST(美国国家标准与技术研究院)和微软研究都指出,这种政策**反效果明显**——它把人逼进了一条可预测的「加固套路」:

实在记不住,就**写在便签贴显示器上**——这反而是更明显的物理泄露;或者依赖浏览器的「记住密码」功能,可同步到云端的安全强度参差不齐。

攻击者早就摸透了这些套路。市面上现成的「密码字典」里,`Password1!`、`Welcome2024!`、`Company@2023` 这一类「看起来强、实际烂大街」的密码早就被收录了。

flowchart LR
    A[网站加码强密码规则<br/>8位+大小写+符号+定期改] --> B[用户记不住]
    B --> C[用有规律的强密码<br/>Zhang2024!]
    C --> D[攻击者用字典破解]
    D --> E[网站再加更严的规则]
    E --> A

一个具体的「密码加固史」

小明为某个账号设密码,看他是怎么一步步「加固」的:

  1. 起点:`123456`(太弱)
  2. 加自己名字:`xiaoming123456`(有规律)
  3. 网站要求加大小写符号:`Xiaoming123456!`(「强」了,但模式清楚)
  4. 90 天后被要求改:`Xiaoming123456@` → `Xiaoming123456#`(只在末尾换符号)
  5. 一年后:`Xiaoming123456$2024`

攻击者拿到这个模式后,下一轮只试十几种变体就能破解。

要点:

人类大脑天生擅长找意义、记不住随机串;强密码规则越严,用户越会用**可预测**的方式应付,结果反而更不安全。

撞库与数据泄露的现实规模

撞库与数据泄露的现实规模

你可能觉得「账号被撞」是别人家的小概率事件。但从行业报告看,这其实是密码时代的**结构性常态**——不是偶发灾难,而是天天都在发生的背景噪音。

一、Verizon DBIR:二十年不变的「第一凶手」

Verizon 每年发布的《数据泄露调查报告》(Data Breach Investigations Report,简称 DBIR)是安全行业最权威的统计来源之一。他们分析全球上万个真实事件,二十年下来最稳定的结论是:

> **约 80% 的黑客相关入侵事件,与「失窃的密码」或「太弱的密码」直接相关。**

这意味着攻击者**根本不需要什么高超技术**——只要拿到一个能用的用户名密码组合,入侵就成功了一大半。这个比例在 2017、2020、2023 年的报告里几乎一致,几乎没变化。它揭示了一个残酷事实:**密码本身就是安全链条上最脆弱的那一环**。

二、数据泄露:从「偶发失火」变成「常态库存」

以前我们觉得「数据库泄露」是个别公司被黑客攻破,是孤例。但 2010 年代以后,几起超大泄露让「别人的密码库」变成了攻击者可以**批发购买**的商品:

这些「历史总库存」今天还在暗网论坛里被反复倒卖,几十 GB 一份,价格便宜到几十美元。攻击者拿到它们,**完全不需要再破解**——密码是明文或者已经离线跑好的哈希对照表,开箱即用。

三、撞库:为什么「一个密码走天下」会害死人

**撞库(Credential Stuffing)** 是当下最泛滥的攻击手段之一。它的逻辑极简,但威力极大:

flowchart LR
    A[网站A数据库泄露<br/>1000万条用户名+密码] --> B[攻击者整理成字典]
    B --> C[批量去网站B C D E<br/>用同一套账号密码尝试登录]
    C --> D{密码是否重复使用}
    D -->|是| E[登录成功<br/>账号被接管]
    D -->|否| F[失败 继续试下一组]
    E --> G[盗走资金/隐私<br/>或继续用此账号钓别人]

为什么这么有效?因为上一节我们刚讲过的现实——**超过 65% 的人在多个网站重复使用相同或近似的密码**。所以一份 A 网站的泄露库,攻击者拿去 B、C、D 批量「撞」,命中率通常在 0.1%–2% 之间。看起来低,但乘以 10 亿条记录,就**轻松进账上万个有效账号**。

微软安全团队在公开研究中也披露过:他们的身份系统每月处理**数十亿次**登录尝试,其中相当比例属于自动化撞库。即使 1% 的成功率,落到全球用户基数上,每月也意味着数百万个本不该登录成功的账号被攻破。

四、把损失换算成钱

IBM 历年《数据泄露成本报告》(Cost of a Data Breach)数据持续走高:

对个人用户来说,损失更直接:账号里的余额被转、信用卡被刷、邮箱被用来给通讯录群发诈骗链接、社交账号被用来冒充身份向亲友借钱。

要点:

密码泄露不是罕见事故,而是攻击者手里**取之不尽的弹药库**;撞库利用的正是人们「一处泄露、处处失守」的复用习惯——这正是密码必须被整个换掉的核心原因。

攻击者常用的偷密码手法

攻击者常用的偷密码手法

你把密码想成「家门钥匙」。要进屋偷东西,小偷要么想办法**拿到钥匙**(偷、骗、猜),要么**把整扇门撬开**。网络攻击也一样——攻击者不需要从你嘴里逼出密码,他们有四套主流手法,能从各种角度把你的密码「顺走」。

一、钓鱼:把假鱼饵扔到你面前

钓鱼(Phishing)是最古老的招数,今天依然最管用。攻击者会**仿造一个长得和你常访问的网站一模一样的登录页**——比如一条「银行账户异常」的短信、一个「快递签收失败」的邮件,附一个链接。你点进去,输入用户名密码,页面提示「登录失败」,你骂一句重输,没当回事。

但密码已经发到了攻击者的服务器上。

现代钓鱼更狡猾:他们能**实时把你在假页面上输的账号密码,转手去真正的网站试一遍**。这种叫「实时钓鱼代理」(real-time phishing proxy)——你输完密码,网站还真的跳出了欢迎页,因为你**真的登进去了**。等你反应过来,账户可能已经被转空了。

钓鱼可怕在哪?它绕过了所有「密码强度」的把戏——你密码设得再长、再复杂,照样亲手敲给了骗子。

二、键盘记录器:你按的每个键都被记下来

键盘记录器(Keylogger)是一种**潜伏在你电脑或手机里的恶意程序**。它可能藏在:

装上之后,它在后台静默运行,**你每次敲键盘都记下来**,打包定期发回攻击者。

如果只偷键盘还好办——很多密码管理器有「自动填充」功能,根本不需要键盘输入。但很多**还在用键盘敲密码的人**,等于把自己的密码主动打成了明文日志。

三、暴力破解:穷举所有可能

暴力破解(Brute Force)就是**把字典里每个可能的密码挨个试**。听起来笨,但非常有效——尤其对短密码。

假设你的密码是 6 位纯数字,一共 100 万种可能。一台普通笔记本一秒钟能试上百万次,**几秒钟破完**。

现代攻击者会用**「常见密码字典」**加速——不用从 000000 开始试,而是直接试 123456、qwerty、password、iloveyou 这种全球前列的弱密码排行。Have I Been Pwned 这样的公开数据库就收纳了**数十亿条**曾经泄露过的真实密码,攻击者下载一份,覆盖了绝大多数用户实际设的密码。

flowchart TD
    A[攻击者准备字典<br/>真实泄露库加常见弱密码] --> B[锁定目标账号]
    B --> C[自动脚本<br/>每秒钟上千次尝试]
    C --> D{密码命中?}
    D -->|是| E[账号被攻破]
    D -->|否| F[继续尝试]
    F --> D

四、撞库:上一节看规模,这一节看方法

上一节我们讲了泄露库的体量有多大。这里补充**攻击者拿到库之后具体怎么用**:

  1. 拿到一份「A 网站的邮箱+密码」列表
  2. 写脚本,把这套组合**批量**发到 B 网站、C 网站、D 网站
  3. 哪个撞上了,哪个账号就「接管」

它的可怕在于:**就算你的密码很强、很独特,只要你在别的网站用过,撞库就替你「试」出来了**。攻击者不需要破解你——他只是把你已经泄露的密码在别处「重放」一遍。

五、其他常见手段(速览)

一个具体例子

小王在三个网站都用同一个密码 P@ssw0rd123:

**小王的电脑从头到尾没被攻破**。他只是多用了同一个密码,攻击者靠「试」就进来了。

要点:

钓鱼骗你亲手交出密码、键盘记录偷你的输入、暴力破解靠字典穷举、撞库靠泄露库「重放」你的复用——**密码时代里,攻击者根本不需要破解你,他们只需要偷、骗、试。**

现有缓解方案的边界

人们意识到密码靠不住之后,过去十年最主流的两种补救措施就是:**双因素认证**和**密码管理器**。这两样东西确实挡住了大量攻击——但**留下来的死角,刚好就是 Passkey 想堵住的那些洞**。这一节我们就来看:它们各自解决了什么,又各自留下了什么。

双因素认证:多了一道锁,但钥匙也可能被偷

双因素认证(2FA,Two-Factor Authentication)的逻辑是:光知道密码不够,**还得证明你拥有某个东西**——通常是手机上的验证码 App,或者一条短信。

它解决的问题是:**密码单独泄露时,攻击者登不进去**。你 A 网站的密码被拖库了,他拿着这个密码去登录,网站要求输入手机验证码,他过不了——他没你的手机。

但 2FA 留了三个没堵上的洞:

**第一,短信验证码可以被劫持。** 攻击者打电话给运营商,谎称「我手机丢了要补卡」,把你的号码转到他的 SIM 卡上。这时候所有短信验证码都发到攻击者手机上,2FA 形同虚设。据 FBI IC3 2023 年报告,SIM 卡交换(SIM Swap)相关投诉造成的损失**约 4,800 万美元**;这只是已报案的部分,实际数字更高。

**第二,实时钓鱼代理连验证码一起骗走。** 上一节我们提过这种攻击:你在假网站上输密码,攻击者实时把请求转发到真网站,真网站弹出验证码又转回给你。你以为是在跟银行交互,其实每一步都被中间人代理了——**密码和 6 位验证码都进了攻击者的口袋**。2FA 在这种攻击面前等于零。

**第三,MFA 疲劳轰炸。** 攻击者已经知道你的密码(从撞库来的),夜里两点钟开始疯狂触发登录请求,每次都给你手机推一条「是否允许登录?」。你被震醒几十次之后,烦了,随手点了「同意」——攻击者进去了。这种招数在 2022 年 Uber 和 Cisco 的大规模入侵里都用过。

密码管理器:把强密码「请」回家,但拦不住被骗

密码管理器(1Password、Bitwarden、Chrome 自带等)的逻辑是:**让你不用记住强密码,工具帮你存、帮你填**。每个网站一个 50 位的随机密码,你也记不住——但你只需要记住「主密码」一个,工具自动帮你登录。

它解决的问题是:**你终于肯用强密码了,终于不复用了**。撞库直接失效,因为你每个网站密码都不一样;暴力破解也失效,因为密码长到几万年都试不完。

但密码管理器也留了三个洞:

**第一,主密码是单一故障点。** 一旦主密码泄露,所有网站密码一起泄露。更糟的是,如果主密码用得弱(比如你拿生日当主密码),等于所有强密码的「金库」就挂在一根线上。

**第二,挡不住钓鱼。** 你被引导到「banlk.com」(拼错的假银行),密码管理器不会识别这是假网站,照样把账号密码填进去——它只会看「这个域名是新的,我没存过」。钓鱼问题对密码管理器来说,**结构上无解**,因为「在假网站填假表单」这个动作从密码管理器视角看完全合法。

**第三,库本身也会泄露。** 2022 年 LastPass 整个用户主密码库被拖走。虽然里面数据是加密的,但弱主密码的用户实质上等于「裸奔」。**你把鸡蛋从一个篮子(自己脑子)换到了另一个篮子(云端密码库)——篮子被端的时候,损失只是换了个形式**。

一个具体例子

小李是个很注重安全的人:每个网站用 1Password 生成不同的 16 位强密码,还开了短信 2FA。

**2FA 在场,密码管理器也在场,密码强度也够。** 但所有工具都被同一个口子绕过了:钓鱼页面 + 实时中转。

一张图看清三类工具的「防护范围」

flowchart LR
    A[用户输入密码] --> B{被哪种攻击}
    B --> C[撞库]
    B --> D[暴力破解]
    B --> E[实时钓鱼中转]
    C --> F[密码管理器拦住]
    D --> F
    C --> G[2FA 拦住]
    D --> G
    E --> H[2FA 也拦不住<br/>验证码也被骗走]
    E --> I[密码管理器也拦不住<br/>域名对得上就照填]

要点

**2FA 解决了「密码单独泄露」,密码管理器解决了「弱密码和密码复用」**——但**钓鱼和实时中转**这两类攻击,是它们**结构上**无法防御的。Passkey 之所以成为业界押注的下一代替代方案,正是因为它在原理上**根本不让你「输入」一个可被偷走的东西**。

学习笔记

密码时代的结构性困境

一、人脑不是随机数生成器

工作记忆一次只能容纳约 5–7 个独立项,这是硬件层面的限制。完全随机的字符串对人脑是「噪声」,无法存进长期记忆。

大脑是「模式识别机器」,天然找规律、找意义、找联想:生日、姓名、宠物名、键盘直线(qwerty、asdf)——这些既是人脑偷懒的方式,也是攻击者最易猜中的方式。

二、群体层面的真实密码行为

三、强密码规则的反效果

为逼用户用强密码,网站加了 8 位以上、大小写、数字、符号、90 天轮换等规则。但 NIST 与微软研究指出,这种政策把人逼进可预测的「加固套路」:

`Password1!`、`Welcome2024!`、`Company@2023` 这类「看起来强、实际烂大街」的密码,早已被收录入公开字典。

四、Verizon DBIR 的二十年结论

约 80% 的黑客相关入侵事件与失窃或太弱的密码直接相关,2017、2020、2023 年报告里比例几乎一致。这意味着攻击者无需高超技术,拿到一对可用凭证就成功一大半。

年 Yahoo 约 30 亿账户

2013 年 Yahoo 约 30 亿账户、2012 年 LinkedIn 约 1.65 亿条密码、2019 年 Collection #1 共 7.73 亿条、2021 年 COMB 47 亿条。这些库在暗网被反复倒卖,价格低至几十美元,密码多为明文或已离线跑好的哈希表。

因为 65% 以上用户跨站复用密码

flowchart LR
    A[网站A数据库泄露<br/>1000万条用户名+密码] --> B[攻击者整理成字典]
    B --> C[批量去网站B C D E<br/>用同一套账号密码尝试登录]
    C --> D{密码是否重复使用}
    D -->|是| E[登录成功<br/>账号被接管]
    D -->|否| F[失败 继续试下一组]

因为 65% 以上用户跨站复用密码,命中率虽仅 0.1%–2%,但乘以十亿条记录,每月可轻松进账上万个有效账号。微软公开研究显示其身份系统每月处理数十亿次登录尝试,其中相当比例属于自动化撞库。

IBM 报告

IBM 报告:2023 年全球一起数据泄露平均成本约 445 万美元;涉及失窃凭证的入侵事件,平均每次比别类多花约 30 万美元善后——合法凭证进入后,攻击者潜伏更久、横向移动更广。

八、四种主流偷密码手法

**钓鱼**:仿造登录页骗用户输入,密码直接发到攻击者服务器。现代「实时钓鱼代理」会把你输的凭证实时转发到真网站,你真登进去,账户随后被清空。钓鱼绕过一切密码强度把戏。

**键盘记录器**:潜伏在电脑或手机的恶意程序,记录每次按键并定期回传。还在用键盘敲密码的人,等于主动把密码打成明文日志。

**暴力破解**:挨个试字典。6 位纯数字共 100 万种组合,普通笔记本每秒可试上百万次,几秒破完。配合 Have I Been Pwned 这类收了几十亿条真实泄露密码的公开数据库,覆盖绝大多数用户实际设的密码。

**撞库**:拿 A 网站泄露库批量去 B、C、D 网站「重放」。就算密码本身很强、很独特,只要在别处用过就被「试」出来。

其他常见手段:肩窥、公共 WiFi 嗅探、密码喷洒(一个常用密码试遍大量账号)。

九、双因素认证的三个死角

短信 2FA 留下了三个未堵上的洞:

十、密码管理器的三个死角

十一、一个具体的失败案例

小李每个网站用 1Password 生成不同的 16 位强密码并开了短信 2FA:

2FA、密码管理器、强密码三道防线同时在场,却被同一个钓鱼流程全部绕过——这正是 Passkey 想堵住的结构性漏洞。

第 2 关 · Passkey 的核心原理——公私钥对与挑战-应答

用门锁类比讲清『公钥-私钥』与『挑战-应答』,理解 Passkey 为何能防服务器泄露

公私钥对:锁与钥匙的比喻

公私钥对:锁与钥匙的比喻

想象一个反常识的挂锁:**关锁不需要钥匙,开锁才需要**。任何人拿到这把锁,都可以「啪嗒」一声把它扣上;但一旦扣上,就只有一个人能打开——那个持有唯一钥匙的人。

这个挂锁就是「公钥」(public key),那把独一无二的钥匙就是「私钥」(private key)。它们是数学上配对生成的一对:公钥负责「锁」,私钥负责「开」。公钥复制一万份发给全世界都没关系——别人能锁,不能开;私钥你自己藏好,一份都不给。

为什么这种「锁」能证明「是我」?

传统密码登录的本质是:你和服务器共享一个秘密(密码),登录时你把这个秘密**原样发过去**让服务器比对。这就像你把家门钥匙复制一份交给物业,每次进门都把钥匙递过去——中间任何一个环节(输错的瞬间、传输的链路、服务器被拖库后的数据库)都可能被复制走。

公私钥对彻底换了一个玩法:

服务器从头到尾**没有收到、也无法推算出你的私钥**。即使服务器被黑客攻破、被「拖库」,黑客拿到的也只是一堆挂锁——没有钥匙,锁再多也开不了任何东西。

flowchart TD
    A[设备生成一对密钥] --> B[公钥 挂锁]
    A --> C[私钥 开锁钥匙]
    B --> D[发给服务器 注册完成]
    C --> E[私钥永远在本地 从不发送]
    D --> F[服务器只存公钥]
    E --> G[登录时设备用私钥作答]
    F --> H[服务器用公钥验证]
    G --> H
    H --> I[服务器被攻破 黑客只拿到挂锁]
一个具体的小例子

假设你在 example.com 注册账号,过程是这样的:

  1. 你的设备(手机/电脑)本地生成一对密钥:公钥 Pub_abc、私钥 Priv_abc
  2. 你的设备把公钥 Pub_abc 发给 example.com,网站把它存进数据库
  3. **私钥 Priv_abc 从头到尾就没出过你的设备**——没被发送、没被备份、没被上传到任何云端

下次你登录 example.com,网站发一个随机数串(比如「今天请证明你是 7f3a2b」),你的设备用 Priv_abc 对这个数做一次「签名」,把签名结果发回去。网站用之前存的 Pub_abc 验证签名——验证通过,就证明你手里确实有 Priv_abc,你就是账号的主人。

整个过程里,网站**从来没收到过 Priv_abc**。即使 example.com 明天数据库泄露,黑客只能拿到一堆公钥——相当于拿到一万把挂锁,没有一把对应的钥匙能开。

这和端到端加密有什么不一样?

你之前接触过的端到端加密(比如聊天软件)是「防偷看」:消息内容只有收信人能解开。Passkey 这里公私钥对干的是另一件事——「防冒充」:用数学方式证明「我确实是我」,而且整个过程不需要把任何秘密传给服务器。前者锁信的内容,后者锁身份本身。

**要点:** 公私钥对的核心是「能锁不能开、能开不能锁」——服务器只拿到挂锁(公钥),开锁的钥匙(私钥)永远在你自己的设备里,所以验证身份时,秘密根本不用出门。

私钥永不离开设备

私钥永不离开设备

上一节我们讲到,公钥是「挂锁」、私钥是「开锁钥匙」。这一节要回答一个更关键的问题:**这把开锁的钥匙,到底放在哪里?**

答案听起来有点极端——它从生成那天起,就一直待在你自己的设备里,从没出过门。

密码登录 vs Passkey:秘密的「旅程」完全不一样

要理解这件事为什么重要,得先看清楚传统密码登录里,密码到底走过多长的路:

你打开网站 → 输入密码「mypassword123」→ 浏览器把这个密码原文发给服务器 → 服务器拿去和数据库里存的对比 → 觉得对,放你进去。

整条链路上,**密码至少要「裸奔」一次**——从你手指敲下到服务器收到的那个瞬间,它是以明文形式存在的。而你完全不知道这条链路中间有多少人能看到它:浏览器插件、你公司路由器的管理员、运营商的某个节点、服务器所在机房的运维……任何一个环节出岔子,密码就泄露了。

更麻烦的是服务器那端。网站为了「下次能验证你」,必须把你的密码(或者密码的哈希值)存进数据库。**这个数据库就是攻击者眼里的金矿**。一旦网站被「拖库」,成千上万用户的密码一次性暴露——然后攻击者拿着这些密码去「撞」别的网站(因为大多数人一套密码走天下),损失就成倍放大了。

Passkey 的设计从根上就避开了这个陷阱:

flowchart LR
    subgraph 传统密码登录
        P1[你输入密码] --> P2[密码经网络发送到服务器]
        P2 --> P3[服务器存进数据库]
        P3 --> P4[数据库被攻破 密码全泄露]
    end
    subgraph Passkey 登录
        K1[私钥生成在设备芯片里] --> K2[私钥从不离开设备]
        K2 --> K3[服务器只存公钥]
        K3 --> K4[服务器被攻破 黑客只拿到一堆挂锁]
    end

注意左边那条链 vs 右边那条链的差别——**私钥从头到尾没出现在网络上,也没出现在服务器的硬盘里**。

那私钥到底藏在哪里?

不是随便放在手机文件系统的某个文件夹里,而是放在设备专门为密钥设计的一块「保险柜」芯片里——iPhone 上叫 Secure Enclave(安全隔区),Android 和 Windows 上叫 TEE(可信执行环境)或 TPM(可信平台模块)。这块芯片有几个特点:

打个比方:这不像你把钥匙藏在抽屉里(抽屉能被撬),更像钥匙被浇筑进了你家门里面的墙体里——它就在那儿,**只有门(芯片)自己能调用它**,外力想取出来,除非把整面墙拆了重建。

一个具体场景:example.com 明天被黑

假设你在 example.com 用 Passkey 注册了账号,私钥存在你 iPhone 的 Secure Enclave 里。然后 example.com 出了安全事故,整个用户数据库泄露。

攻击者拿到的数据长这样:

**他拿不到任何可以登录你账号的东西**。因为:

  1. 公钥本来就是「挂锁」——只能锁不能开
  2. 私钥从来没在服务器出现过
  3. 没有私钥,就无法对服务器的新挑战签名,无法通过验证

这件事就是 Passkey 真正革命性的地方:**它把「被攻破」的代价从「全员密码泄露」降到了「全员需要重新注册」**。公钥泄露就泄露吧,那本来就是公开的东西。

同步:私钥真的「永远」不出设备吗?

这里有个诚实的细节要告诉你:如果只存在一台设备上,那换手机、换电脑就很麻烦。所以现代 Passkey 方案(iCloud 钥匙串、Google 密码管理器、1Password 等)会用**端到端加密**把私钥同步到你的其他设备——但同步通道是加密的,**连同步服务商自己都看不到私钥的明文**。这跟我们在第一关学过的端到端加密是一回事。

**要点:** Passkey 的安全核心不是「算法有多复杂」,而是「**服务器上根本没有秘密可偷**」——私钥从生成那天起就被焊死在你的设备芯片里,从不发送,从不上传,连网站被黑都不会泄露。

挑战-应答:不传密码也能证明『是我』

想象你们班有个老师,要确认今天来上课的人是不是真学生张伟。一种办法:张伟每次都把身份证交给老师看——但身份证每次离开张伟的手,就有被复制或调包的风险(这就是密码的处境)。

老师用了一种更聪明的方式:**他每节课随机出三道题,让张伟当场在黑板上作答**。比如今天出「3 × 7 等于几」「中国首都是哪儿」「把『窗户』的英文写在黑板上」,明天出完全不同的题。

这样做有两个关键效果:

挑战-应答就是这套机制的网络版。

挑战-应答的三步流程

当你在 example.com 用 Passkey 登录时,浏览器背后其实发生了一场三方问答:

flowchart LR
    A[服务器生成一串随机字符<br>即挑战] --> B[服务器把挑战发给浏览器]
    B --> C[浏览器把挑战交给设备芯片]
    C --> D[私钥对挑战做数学签名<br>即应答]
    D --> E[浏览器把应答送回服务器]
    E --> F[服务器用之前存的公钥验证]
    F --> G{反算结果<br>对得上原挑战?}
    G -->|是| H[放行 登录成功]
    G -->|否| I[拒绝]

每一步对应到人话:

  1. **服务器出题**:在你点下「登录」那一刻,服务器临时生成一串随机字符(比如 `c8d9a1f3-7b2e-4d6a-...`,64 个十六进制字符),这就是「挑战」。这串字符完全随机、只用一次、几秒钟后作废。
  2. **你用私钥作答**:浏览器把这串挑战送进设备芯片。芯片调用私钥,对挑战做一次**数学签名**——得到的签名就叫「应答」。
  3. **服务器验证**:服务器拿到应答后,用**当初你注册时存下来的公钥**反算:「如果应答真的来自对应私钥,那反算结果必须等于原挑战。」对得上,说明确实是那把私钥签的,登录成功。
为什么「随机」这两个字至关重要

挑战必须是**每次都不同、不可预测、用完即弃**的。这是为了堵死一类叫「重放攻击」的风险。

设想挑战是一道固定题,比如永远是「3 × 7 = ?」。攻击者只要在网络上偷听到一次应答(也就是「21」),下次登录时直接把这个应答原封不动发给服务器就行——因为服务器看到的「应答 21」本身是合法的。**这就像有人把你的答卷拍照抄走,明天换了张试卷,但答案他直接抄昨天那张。**

而真实挑战是 256 位的随机数,可能性多到比宇宙里的原子数还多。攻击者就算截获了昨天的应答,今天服务器出的是完全不同的新题,**旧应答在新挑战下根本验不过**。整套机制天然免疫重放。

一个具体例子

假设你登录 example.com:

**整个过程,私钥没有离开过你的设备芯片,挑战-应答也只在这次登录有效**。即使有人把这趟的应答完整记下来,下一秒他拿它去登录 example.com,服务器丢出来的是新挑战,旧应答就成了废纸。

那公钥为什么能验签?

简单提一句(细节不用钻进数学里):公钥和私钥在数学上是「配对」的,私钥签的签名,公钥一定验得过;**但从公钥倒推私钥,理论上几乎不可能**(要算到宇宙毁灭那么久)。所以服务器拿着公钥就能放心地验——验过了,就等于「持私钥者确实到场」,而持私钥者全天下只有你那台设备。

**要点:** Passkey 登录没有传输任何「能复用的秘密」——服务器每次出随机题,你用私钥现场作答,应答一次性使用。哪怕这趟的应答被偷走,下趟也完全作废;这就是它从机制上免疫重放攻击、能证明「是我」的原理。

生物识别与设备 PIN 的真实角色

上一块我们讲完挑战-应答后,你心里可能冒出一个问题:「那要是我手机被人偷了,对方拿着我手机是不是就能直接登录所有网站?毕竟私钥就在手机里。」

答案是:不行。**因为私钥还被锁在另一道门后面——这道门只有你能开。** 这道门的钥匙,就是 Face ID、Touch ID 和设备 PIN。

私钥是「双重上锁」的

我们重新理一下你手机里这把私钥的真实处境。想象你把家里最重要的东西存进了银行金库:

**没有身份证和签名,你连金库大门都进不去,更别说打开保险箱。** Face ID 和设备 PIN 的角色,就是设备**本地**用来证明「你确实是这台手机的合法持有者」。它们在设备内部核验,核验结果从不出门。

一次登录到底发生了什么

把前面几块串起来,你点「用 Passkey 登录 example.com」的完整流程是这样的:

flowchart TD
    A[你点登录] --> B[example.com 生成随机挑战]
    B --> C[挑战发到你的手机]
    C --> D{手机检测:<br>私钥被锁着}
    D -->|需要解锁| E[手机要求 Face ID 或 PIN]
    E --> F{本地验证通过?}
    F -->|否| G[拒绝 流程终止]
    F -->|是| H[Secure Enclave 内部:<br>私钥对挑战做签名]
    H --> I[签名发回 example.com]
    I --> J[服务器用公钥验证]
    J --> K{验证通过?}
    K -->|是| L[登录成功]
    K -->|否| M[拒绝]

注意这条分界线:**F 到 H 全在你手机内部发生**。Face ID 验证完,私钥被释放,签名被算出来——这一切都在 Secure Enclave 这块独立芯片里完成。离开手机的,只有签名后的应答。

你的人脸数据到底去了哪里

这是最反直觉、但也最关键的一点:**你的脸、指纹、设备 PIN——没有任何一项被发往 example.com。**

服务器端存的是:

服务器端**不存**的是:

所以即便 example.com 明天被黑客攻破,泄露出去的用户数据里**找不到你的脸**——因为网站根本就没存过。这和密码登录时代完全不同:过去密码泄露,攻击者拿到的就是「能直接登录你账号的东西」;而今即使网站全库泄露,攻击者拿到的也只是公钥——公钥验签可以,反推私钥算到宇宙毁灭也算不出来。

PIN 不是「比 Face ID 弱」的备胎

很多人误以为「PIN 是 Face ID 的降级方案,肯定没 Face ID 安全」。其实在 Passkey 这件事上,**它们的作用完全一样**:都是本地解锁私钥的凭证。

PIN 的真正价值是「万无一失的兜底」:Face ID 在你戴口罩、刚起床脸肿、黑暗环境里可能识别失败,这时候 PIN 顶上。只要 PIN 没被猜到,私钥就还在锁着。

这就是为什么设置一个**足够长、足够独特**的设备 PIN 极其重要——它实际上是 Passkey 的最后一道防线。

**要点:** Face ID、Touch ID、设备 PIN 的作用都是「在本地解锁私钥」,它们核验的是「你是否是这台设备的合法持有者」,核验结果从不上传;网站只收到签名后的应答,所以即使网站被攻破,你的生物特征和 PIN 也不会泄露。

学习笔记

Passkey 的核心原理:公私钥对与挑战-应答

公私钥对:能锁不能开,能开不能锁

公钥相当于一把反常识的挂锁:任何人拿到都能「啪嗒」扣上,但只有一把钥匙能打开。公钥是锁,私钥是唯一的钥匙,两者由数学配对生成。

公钥可以复制一万份发给全世界,私钥一份都不能给,必须自己藏好。

服务器只存公钥的验证逻辑

服务器只持有公钥,设备只存私钥。验证身份时,服务器出一道随机题,设备用私钥按对应方式「作答」,服务器用公钥查对——答对就放行。整个过程服务器从未收到、也无法推算出私钥。即使服务器被「拖库」,黑客拿到的也只是一堆挂锁,没有对应钥匙打不开任何东西。

flowchart TD
    A[设备生成一对密钥] --> B[公钥 挂锁]
    A --> C[私钥 开锁钥匙]
    B --> D[发给服务器]
    C --> E[私钥永远在本地]
与端到端加密的区分

端到端加密锁的是「消息内容」防偷看;公私钥对锁的是「身份本身」防冒充。两者目的不同:前者保护信的内容,后者证明「我确实是我」,且全程不需要把任何秘密传给服务器。

私钥永不离开设备

密码登录与 Passkey 登录的秘密「旅程」对比

传统密码登录:用户输入密码 → 浏览器把密码原文发给服务器 → 服务器存入数据库。密码至少有一次「裸奔」——从用户敲下到服务器收到的瞬间是明文;服务器数据库被攻破后,用户密码成批泄露,黑客还会拿这些密码去「撞」其他网站。

Passkey 登录:私钥生成在设备芯片里 → 私钥从不离开设备 → 服务器只存公钥。即使服务器被攻破,黑客拿到的只是一堆挂锁。

flowchart LR
    subgraph 传统密码登录
        P1[你输入密码] --> P2[密码经网络发送] --> P3[服务器存进数据库] --> P4[数据库被攻破 密码全泄露]
    end
    subgraph Passkey 登录
        K1[私钥生成在设备芯片] --> K2[私钥从不离开] --> K3[服务器只存公钥] --> K4[服务器被攻破 黑客只拿到挂锁]
    end
私钥的硬件级藏身处

私钥放在设备专门为密钥设计的「保险柜」芯片里:iPhone 叫 Secure Enclave(安全隔区),Android/Windows 叫 TEE(可信执行环境)或 TPM(可信平台模块)。

这块芯片的特点:

挑战-应答:每次题目不同,旧答案自动作废

三步流程
flowchart LR
    A[服务器生成随机挑战] --> B[服务器把挑战发给浏览器]
    B --> C[浏览器把挑战交给设备芯片]
    C --> D[私钥对挑战做数学签名 即应答]
    D --> E[浏览器把应答送回服务器]
    E --> F[服务器用公钥反算验证]
    F --> G{对得上原挑战?}
    G -->|是| H[放行]
    G -->|否| I[拒绝]

每一步的含义:

  1. 服务器出题:用户点登录瞬间,服务器临时生成一串随机字符(讲义示例为 64 个十六进制字符),即「挑战」,完全随机、只用一次、几秒钟后作废
  2. 设备作答:浏览器把挑战送进设备芯片,芯片调用私钥对挑战做数学签名,签名结果即「应答」
  3. 服务器验证:用注册时存下的公钥反算,「反算结果必须等于原挑战」——匹配即登录成功
「随机」为何至关重要

挑战必须每次不同、不可预测、用完即弃,否则会遭到「重放攻击」:若挑战固定(讲义示例为永远是「3×7=?」),攻击者只要偷听到一次应答(「21」),下次直接把「21」原样发给服务器就蒙混过关。

真实挑战是 256 位的随机数,可能性远超宇宙原子总数。攻击者就算截获了昨天的应答,今天服务器抛出的也是完全不同的新题,旧应答在新挑战下根本验不过——整套机制天然免疫重放。

公钥能验签但反推不出私钥

公钥和私钥在数学上「配对」:私钥签的签名公钥一定验得过,但从公钥倒推私钥理论上几乎不可能(要算到宇宙毁灭那么久)。所以服务器可以放心拿着公钥验签,验过了就证明对方确实持有对应私钥。

生物识别与设备 PIN:私钥的「第二道锁」

私钥的双重上锁结构

私钥被锁在两道门后:

没有身份证和签名,连金库大门都进不去,更别说打开保险箱。Face ID 和设备 PIN 在设备内部核验,核验结果从不出门。

完整登录流程的边界
flowchart TD
    A[你点登录] --> B[服务器生成随机挑战]
    B --> C[挑战发到手机]
    C --> D{手机检测: 私钥被锁着}
    D -->|需要解锁| E[手机要求 Face ID 或 PIN]
    E --> F{本地验证通过?}
    F -->|否| G[拒绝 流程终止]
    F -->|是| H[Secure Enclave 内部 私钥对挑战做签名]
    H --> I[签名发回服务器]
    I --> J[服务器用公钥验证]
    J --> K{验证通过?}
    K -->|是| L[登录成功]
    K -->|否| M[拒绝]

关键分界线:F→H 全在手机内部发生。Face ID 验证完,私钥被释放、签名被算出来——这一切都在 Secure Enclave 这块独立芯片里完成。离开手机的只有签名后的应答。

生物数据从不发往服务器

服务器端存:用户名、公钥、Passkey ID。 服务器端不存:脸部特征、指纹、设备 PIN 明文、私钥。

所以即便网站被黑,泄露的数据里也找不到你的脸——网站根本没存过。公钥能验签,但反推不出私钥。

PIN 不是 Face ID 的「降级备胎」

在 Passkey 这件事上,Face ID 和 PIN 作用完全一样:都是本地解锁私钥的凭证。

PIN 的真正价值是「万无一失的兜底」:Face ID 在戴口罩、刚起床、黑暗环境里可能失败,这时候 PIN 顶上。PIN 实际上是 Passkey 的最后一道防线,设置足够长、足够独特的设备 PIN 极其重要。

第 3 关 · Passkey 为何能根治密码问题

一次性讲清 Passkey 在防泄露、防钓鱼、防重放、用户体验上的核心收益

服务器被黑也不再是大灾难

服务器被黑也不再是大灾难

上一块我们说:公钥是挂锁,私钥是钥匙——服务器只存挂锁,私钥从没有出过你的设备。这一节我们把这个设计放进「服务器被拖库」这种最坏场景下,看看它到底意味着什么。

密码时代的「拖库」灾难

所谓「拖库」,就是黑客攻破网站服务器,把用户数据库整个打包偷走。在密码时代,数据库里存的是「用户名 + 密码(哈希)」(很多网站甚至明文存)。这种数据一旦泄露,后果是连锁的:

Passkey 时代的拖库:偷到的全是「废锁」

回到 Passkey 的设计:服务器只存公钥。

假设攻击者这次下了狠手,把整个用户数据库都偷走了。打开一看,里面是 1 亿条「公钥 + 计数器」记录。然后呢?

**打个比方**:你偷了 1000 万把挂锁(公钥),但全世界的钥匙(私钥)都在用户家里、锁在保险柜里。你能拿这些挂锁干什么?开别人家的门?开自己家门?一把都打不开。

flowchart LR
    subgraph 密码时代
        A1[用户输入密码] --> B1[服务器存密码或哈希]
        B1 -->|服务器被黑| C1[攻击者拿到哈希]
        C1 --> D1[撞库试其他网站]
        C1 --> E1[字典攻击还原明文]
    end

    subgraph Passkey 时代
        A2[设备生成密钥对] --> B2[服务器只存公钥]
        B2 -->|服务器被黑| C2[攻击者只拿到公钥]
        C2 --> D2[公钥无法登录]
        C2 --> E2[无法还原私钥]
    end

从「用户背锅」到「系统兜底」

密码时代的根本困境在于:用户必须把秘密(密码)告诉服务器,服务器必须保管这个秘密。这就把安全责任死死压在了最弱的两环——人脑记忆和服务器数据库。

Passkey 翻转了这个责任结构:

你只是把钥匙揣在自己兜里,从来没把钥匙给过任何人。服务器被黑——对不起,里面没有能开你门的东西。撞库?根本没有「库」可以被撞,因为用户的秘密从一开始就不在服务器上。

这是安全设计哲学上的根本变化:从「靠用户守口如瓶 + 服务器固若金汤」的双重依赖,变成「系统结构上不依赖秘密」。

要点

服务器只存公钥,意味着即使整个数据库被偷,攻击者拿到的也只是一堆打不开的「挂锁」——**服务器被黑 ≠ 账户被黑**。这就是 Passkey 在防泄露维度上对密码的降维打击。

钓鱼网站天然拿不走 Passkey

钓鱼网站天然拿不走 Passkey

上一节我们说:服务器被偷,偷到的全是打不开的「挂锁」。但现实里,绝大多数账号失窃并不是因为服务器被黑——而是**用户主动把钥匙交出去**。这一节就讲讲钓鱼攻击为什么对 Passkey 失效。

钓鱼攻击:今天头号的安全杀手

在密码时代,钓鱼(Phishing)是排名第一的攻击方式。攻击者做一个和真网站一模一样的登录页(比如 `bank-login.com` 模仿 `bank.com`),通过短信、邮件、聊天群发链接。用户一点开,看到熟悉的 logo、熟悉的输入框、熟悉的文案——于是输入用户名密码,「登录」。

没有任何技术上的奇迹发生:用户看到的输入框就是一个普通网页表单,**用户往里填什么,表单就把什么送给攻击者的服务器**。密码本身就是「用户输入的文本」——不管谁问,只要长得对,用户就愿意给。

更狠的是 2020 年以后流行的高级变种:**中间人代理钓鱼(AiTM)**。攻击者甚至不偷密码,而是实时坐在用户和真银行之间——用户访问钓鱼链接,钓鱼站替用户去真银行登录,拿到登录会话后让用户继续操作。整个过程用户感觉毫无异常,密码、短信验证码全都用了。这种攻击连 MFA 都能绕过。

Passkey 的解法:私钥和域名「焊死」

Passkey 在协议层面堵死了这条路。WebAuthn 标准规定:注册时,Passkey 与一个叫 **RP ID(Relying Party ID)** 的域名绑定,通常就是网站的真实主域(如 `bank.com`)。这个绑定不是写在某个配置文件里让你「记得填」——是**在私钥生成时就和私钥一起封装进设备**,私钥在硬件里就认这个域名。

登录时流程是这样:

  1. 用户访问 `bank.com`,服务器发来一道随机挑战
  2. 浏览器/系统把这个挑战连同**当前页面的真实来源**(`https://bank.com`)一起送给设备里的认证器
  3. 认证器检查:「这个请求来自 bank.com?是我绑定的那个 RP ID?匹配,签。」

如果用户其实停留在 `bank-login.com`(钓鱼站),无论页面做得再像,浏览器报给认证器的来源就是 `bank-login.com`,**不是 `bank.com`**。认证器一看对不上号,直接拒绝签名——连「用户能不能解锁」这一步都到不了。

flowchart TD
    A[用户点击链接] --> B{当前页面真实来源}
    B -->|bank.com 真站| C[认证器核对 RP ID]
    C -->|匹配| D[用户面容或指纹解锁私钥]
    D --> E[私钥对挑战签名]
    E --> F[登录成功]
    B -->|bank-login.com 钓鱼站| C2[认证器核对 RP ID]
    C2 -->|不匹配| D2[认证器拒绝签名]
    D2 --> E2[无任何凭据泄露]

「页面长得像」根本不重要

这里要破一个直觉:**我们以为钓鱼攻击能成功的关键是「页面像不像」,其实关键是「用户愿不愿意把东西交出去」。**

密码时代的用户是被骗着主动交出密码的——页面越像,骗局越成功。

Passkey 时代用户**根本没有「交出私钥」这个动作**。私钥出不了设备,操作系统不提供这个 API。钓鱼站能让用户做的事是「点击登录」——但点击后浏览器自动把页面来源告诉认证器,认证器自己核对,对不上就拒绝,**整个过程用户甚至不会看到任何错误提示,因为根本没走到解锁那一步**。

更妙的是 AiTM 代理钓鱼也失效了:用户要登录真银行,必须先在真银行的页面触发认证,钓鱼站没办法把 `bank.com` 的真实页面塞进自己的域名里,浏览器地址栏的来源是改不了的(除非有浏览器 0day 漏洞,那是另一回事)。

要点

Passkey 的私钥从出生起就和真实域名绑定,**钓鱼站无论页面多像、域名多接近,认证器都会因为来源对不上而拒绝签名**——这让钓鱼攻击从「靠用户上当」变成了「靠协议漏洞」,难度提升了好几个数量级。

每一次登录都是『一次性答案』

每一次登录都是「一次性答案」

上一节我们说钓鱼站套不走 Passkey。但还有一种更狡猾的攻击:攻击者**不动你的私钥,只偷偷录下你某次登录的「通信过程」,然后原样再放一遍**——这种攻击叫「重放(Replay)」。密码时代它非常容易成功;Passkey 时代,服务器和私钥联手让每一次签名都变成「一次性用品」。

什么是重放攻击

打个比方:老式小区门卫认暗号,每天进出你对他说「天王盖地虎」,他放你进去。某天有个人躲在树后面偷听到了你的暗号——之后他每次都对门卫说「天王盖地虎」,门卫照样放行。暗号本身没变,攻击者反复用,就反复有效。

密码登录就有这个问题:你的密码永远是那个字符串。如果某次网络传输被监听(公共 WiFi 抓包、流量被劫持、中间人代理等),密码被截获,攻击者之后可以反复用这个密码登录。哪怕你立刻改了密码,在改之前的窗口期内攻击者已经可以登录无数次。

短信验证码本来想解这个问题——每条都不一样嘛——但短信可以被 SIM 卡劫持(SIM swap)或通过伪基站实时转发,且 6 位数字只有百万种组合,攻击者实时截到一条就能立即用,并不算真的一次性。

挑战-响应:服务器出一道「当场新题」

Passkey 的核心协议是**挑战-响应(Challenge-Response)**:

  1. 你打开登录页,服务器立刻**现场生成一串随机数**(叫「挑战」),通过网页发给你的设备。可以理解为:服务器拿出一张白纸,写了一道独一无二的数学题。
  2. 你的人脸或指纹解锁设备里的私钥,私钥对着这道题**签名**——就像用一把独一无二的印章盖在白纸上。签完名,**私钥继续锁在设备里,从头到尾没出过设备**。
  3. 服务器收到签名,用之前存好的公钥验证:「这个签名确实是用对应私钥盖的,而且签的就是我刚出的那道题。」验证通过,登录成功。

关键在哪?**那张白纸(挑战)每次都是新的**。服务器从密码学安全的随机数生成器里现抓一串,长度通常是 32 字节(256 位),整个宇宙的寿命里出现重复的概率都几乎为零。

flowchart LR
    A[服务器现场出题<br/>随机挑战] -->|发给设备| B[用户解锁私钥]
    B --> C[私钥对挑战签名]
    C -->|签名回传| D[服务器用公钥验签]
    D -->|匹配| E[登录成功]
    D -->|不匹配| F[拒绝登录]

为什么「录下来重放」没用

现在攻击者想重放:他在你某次登录时,全程录下了服务器发来的挑战、和你设备返回的签名。下一分钟他想原样再发一次给服务器——

这就好像门卫今天改规矩了——不认暗号,改成「我问你 1+1 等于几,你答 2」。录下你昨天回答「2」的录音没用,他今天问「3+4」,你得当场答「7」。**没有私钥,攻击者永远答不上服务器当下出的新题**。

中间人代理:连「实时转发」也没用

有人会想到:那攻击者不重放历史,而是**实时坐在你和服务器中间**做「传声筒」——你发请求他转发、服务器回挑战他转发、你签完名他再转发。这样他虽然看不到私钥(私钥从不出设备),但他是不是能「借」你的签名登录一次?

也不行,三层原因:

  1. **TLS 加密通道**:浏览器和服务器之间正常情况是 HTTPS 加密的,中间人看不到明文。这层加密是 1990 年代以来的标配,攻击者要破它需要极强算力,不是常规威胁。
  2. **TLS 1.3 的前向保密**:就算他神奇地拿到了某个旧会话密钥,TLS 1.3 用的是临时密钥(前向保密),每次会话密钥不同,录一段也破不了下一段。
  3. **签名本身只对当前挑战生效**:就算他实时截到了你的签名并转发给真服务器,**这道签名只对当前那道挑战有效**,服务器用过一次就作废;他下次登录,服务器又是新挑战,他又没私钥签不出来。

一次性,是整套防御的底层逻辑

把前三节串起来看:

| 攻击方式 | 密码时代的结局 | Passkey 为什么无效 | |---------|--------------|------------------| | 服务器被偷数据库 | 撞库攻击泛滥 | 只有公钥,私钥不在 | | 钓鱼站骗用户输入 | 用户乖乖交出密码 | 域名对不上,私钥不动 | | 重放录制的登录请求 | 反复用截获的密码 | 每次挑战新,签名只对一次有效 | | 实时中间人代理 | 拿走密码或 MFA 会话 | 私钥不出设备,新挑战签不出来 |

你会发现,Passkey 并没有发明什么「绝对破不了」的密码学——它真正做的事是**让「凭据」从「用户记住的字符串」变成「当场计算的一次性签名」**。**攻击者能偷的(公钥、域名对得上的签名记录、旧签名)全都没用;攻击者需要的(私钥、当前挑战的有效签名)他都拿不到也造不出**。

这才是「Passkey 根治密码问题」最底层的那一块拼图。

要点

服务器每次登录都出一道独一无二的随机题,私钥只对当前这道题签名;签名一旦用过即作废,**没有私钥的攻击者既录不下「未来能用」的答案,也实时答不上「现在这道题」**——重放和中间人代理两类经典攻击因此全部失效。

用户体验上的反转

用户体验上的反转

前三节都在讲 Passkey 比密码「更扛打」——服务器被黑没事、钓鱼站套不走、录下登录也没用。但有个反直觉的事实:Passkey 之所以能取代密码,最强的武器不是它更安全,而是**它更简单**。这一节讲这个「反转」,以及它怎么反过来又加固了安全。

密码时代的体验:「四步走,每一步都可能出错」

你是市场运营出身,应该对「用户行为漏斗」很熟——每多一步操作就掉一批人。密码登录就是典型的「漏斗灾难」:

  1. **想**:用户要想「我这个网站用哪个密码来着」——是用专门为这个网站设的那个,还是统一用一个?
  2. **记**:记不住就触发「找回密码」流程,通常要走邮件、短信验证码、设新密码三步。
  3. **敲**:在登录框里一个字符一个字符敲。手机端尤其痛苦——大小写、特殊符号、长串字母混着数字,输错两三次是常态。
  4. **忘**:忘了就回到第 1 步,或者干脆放弃。「忘记密码」按钮几乎所有网站点击率都排前列。

这套流程里,用户每一步都可能在做「**不安全的合理化**」:因为太难记,所以多个网站共用同一个简单密码;因为太难输入,所以存在备忘录里、写在便签上、甚至发到自己的微信收藏。这些「合理化」正是攻击者最爱的入口——撞库靠的就是「一个网站泄露的密码能在别处通用」。

Passkey 的体验:「点一下 / 看一次」

用 Passkey 登录,**用户能感知到的操作只有一步**:

对用户来说,**整件事的体感就是「我证明了我就是我」**——后面的公私钥运算、挑战签名,全部在后台跑了,跟用户无关。

flowchart TD
    A[用户操作] --> B{登录方式}
    B -->|密码| C[想]
    C --> D[记]
    D --> E[敲]
    E --> F[忘?找回?]
    F --> G[可能放弃]
    B -->|Passkey| H[点一下 或 看一次]
    H --> I[登录完成]

反转在哪:安全的路比不安全的路更短

这是 Passkey 真正「反人性」的地方——它让**走安全路线的用户成本比走不安全路线更低**:

用产品的话讲:**Passkey 把「安全」从「用户需要努力达成的状态」,变成了「系统默认就给的状态」**。这才是它真正厉害的地方——它不是说服用户变安全,是让用户根本不需要操心「安不安全」这件事。

这个反转怎么反过来又加固了安全

更短的体验链 = 更少的人类决策点 = 更少的犯错空间:

用户体验和安全不是「鱼与熊掌」——**当流程被重新设计过以后,它俩可以是同一件事的两个面**。这也是为什么 Apple、Google、Microsoft、GitHub、PayPal、京东、华为等都在力推 Passkey:它不是给安全加压,是给用户减负。

要点

Passkey 用「点一下 / 看一次」把登录体验压成单步,**让最安全的路变成最短的路**;用户不再需要「想、记、敲、忘」,也就自然没了弱密码、复用、便签、钓鱼输入等所有可乘之机——**安全靠流程设计自动达成,而不是靠用户努力。**

学习笔记

Passkey 为何能根治密码问题

一、服务器被拖库:偷到的全是「废锁」

**密码时代的拖库灾难**:拖库指黑客攻破服务器,偷走整个用户数据库。数据库里存的是「用户名 + 密码(哈希)」,很多网站甚至明文存储。一旦泄露产生连锁后果:撞库(用户在多网站复用同一或近似密码,攻击者拿 A 网站的密码批量去试 B、C、D),哈希破解(MD5、SHA-1 等快速哈希或明文,字典、彩虹表、GPU 集群几小时可还原几十万常用密码)。代表案例:2012 年 LinkedIn 1.17 亿条密码哈希被偷,半年内大部分被还原;2012 年 CSDN 600 万用户明文密码被公开;2017 年雅虎 30 亿账号全量泄露。每次大型拖库后用户只能改密码,但对撞库而言往往已经晚了。

**Passkey 时代的拖库场景**:服务器只存公钥,攻击者偷走的是「公钥 + 计数器」记录。公钥只能验证签名,答不上服务器发的随机挑战;把公钥复制到攻击者设备也没用,私钥在硬件隔离存储中,操作系统和浏览器都不允许导出,应用也拿不到。比喻:偷了 1000 万把挂锁,全世界的钥匙都在用户家里的保险柜里,一把都打不开。

**责任结构翻转**:密码时代把安全责任死死压在「人脑记忆 + 服务器数据库」两环——用户必须把秘密告诉服务器,服务器必须保管这个秘密。Passkey 时代用户不需要记任何秘密,服务器不需要保管任何秘密。从「靠用户守口如瓶 + 服务器固若金汤」的双重依赖,变成「系统结构上不依赖秘密」。

**核心结论**:服务器被黑 ≠ 账户被黑。这是 Passkey 在防泄露维度上对密码的降维打击。

二、钓鱼攻击:私钥与域名「焊死」

**钓鱼的现实威胁**:钓鱼(Phishing)是密码时代排名第一的攻击方式。攻击者做与真网站一模一样的登录页(如 `bank-login.com` 模仿 `bank.com`),通过短信、邮件、聊天群发链接。页面就是普通网页表单,用户往里填什么,表单就把什么送给攻击者服务器。2020 年后流行 AiTM(中间人代理钓鱼):攻击者实时坐在用户和真银行之间,替用户去真银行登录,拿到登录会话后让用户继续操作,密码、短信验证码全都用了,连 MFA 都能绕过。

**Passkey 的解法**:WebAuthn 标准规定,Passkey 在注册时与一个叫 RP ID(Relying Party ID,通常是网站主域如 `bank.com`)的域名绑定。这个绑定在私钥生成时就和私钥一起封装进设备,私钥在硬件里就认这个域名。登录流程:用户访问 `bank.com`,服务器发来随机挑战;浏览器/系统把挑战连同当前页面的真实来源(`https://bank.com`)一起送给设备里的认证器;认证器检查当前来源是否与绑定的 RP ID 匹配,匹配才签。

**对钓鱼站为何天然失效**:用户若停留在 `bank-login.com`,浏览器报给认证器的来源就是 `bank-login.com`,不是 `bank.com`,对不上 RP ID,认证器直接拒绝签名——连「用户能不能解锁」这一步都到不了。钓鱼站能让用户做的只是「点击登录」,但点击后浏览器自动把页面来源告诉认证器,对不上就拒绝,整个过程用户甚至不会看到任何错误提示,因为根本没走到解锁那一步。AiTM 也失效:用户要登录真银行必须在真银行页面触发认证,钓鱼站无法把 `bank.com` 的真实页面塞进自己的域名。

**关键认知修正**:钓鱼攻击能成功的关键不是「页面像不像」,而是「用户愿不愿意把东西交出去」。Passkey 时代用户根本没有「交出私钥」这个动作,私钥出不了设备,操作系统不提供这个 API。

三、重放攻击:每一次签名都是「一次性答案」

**重放攻击**:攻击者不动你的私钥,只偷偷录下某次登录的「通信过程」,然后原样再放一遍。比喻:老式小区门卫认暗号「天王盖地虎」,攻击者躲在树后偷听后反复用,反复有效。密码登录的弱点:密码永远是那个字符串,被截获后可反复使用,哪怕立刻改了,在改之前的窗口期内攻击者已可登录无数次。短信验证码的局限:可被 SIM 卡劫持或伪基站实时转发,且 6 位数字只有百万种组合,实时截到一条就能立即用,不算真的一次性。

**挑战-响应机制**:Passkey 核心协议是挑战-响应(Challenge-Response)。用户打开登录页,服务器现场生成一串随机数(挑战,通常 32 字节/256 位,从密码学安全的随机数生成器里现抓,整个宇宙寿命内出现重复的概率几乎为零)发给用户设备;用户人脸/指纹解锁私钥,私钥对挑战签名,私钥从头到尾没出过设备;服务器用公钥验证签名,确认是对应私钥签的且签的就是自己刚出的那道题。比喻:服务器拿出一张白纸写独一无二的数学题,私钥用独一无二的印章盖上去。

**为什么重放无效**:服务器收到「旧签名」后不会去验旧挑战,只认自己刚现生成的那道新挑战。录下的签名是针对上一道题的答案,对新题目就是废纸。服务器一查签名对应的挑战号要么已用、要么对不上当前挑战,拒收。比喻:门卫每天换新题,录下昨天的答案对今天的新题无用。没有私钥,攻击者永远答不上服务器当下出的新题。

**中间人代理也无效**:浏览器和服务器之间正常情况是 TLS 加密通道(1990 年代以来的标配),中间人看不到明文。

四、用户体验反转:安全路比不安全路更短

**密码时代的体验漏斗**:四步——想(这个网站用哪个密码)、记(记不住触发「找回密码」流程:邮件、短信验证码、设新密码三步)、敲(逐字输入,手机端尤其痛苦,大小写、特殊符号混着数字,输错两三次是常态)、忘(回到第 1 步或干脆放弃)。每一步都在做「不安全的合理化」:因为太难记所以多网站共用同一简单密码;因为太难输入所以存在备忘录里、写在便签上、发到微信收藏。这些「合理化」正是撞库赖以生效的入口。

**Passkey 的体验**:用户能感知到的操作只有一步。浏览器弹系统对话框「使用你的 iPhone / Windows Hello / 安全密钥登录」,用户按 Touch ID / Face ID / 指纹 / 扫安全密钥,完事。体感就是「我证明了我就是我」,后面的公私钥运算、挑战签名全部在后台跑,跟用户无关。

**反转核心**:过去安全的做法(给每个网站设一个 16 位随机强密码、用密码管理器、定期更换)操作成本极高;不安全的做法(所有网站共用一个简单密码)操作成本极低,绝大多数人选了不安全的。用 Passkey 时,安全的做法就是「点一下」;不安全的做法(回到密码登录、自己管理密码)反而更麻烦。攻击者设的钓鱼站需要用户「输入」东西,Passkey 用户根本没有输入框可填,那条路天然断掉。Passkey 把「安全」从「用户需要努力达成的状态」变成「系统默认就给的状态」——不是说服用户变安全,是让用户根本不需要操心安全。

**体验链缩短反过来加固安全**:没有「我密码忘了」环节,就没有弱密码、没有复用、没有便签贴纸条、没有密码管理器主密码被钓鱼;没有「输入框」环节,钓鱼站没地方套你东西,进假网址也不会弹出 Passkey 对话框(域名对不上),自带一道防线。

第 4 关 · 注册与登录的完整流程

能完整讲出用户在网站/App 上启用 Passkey 与用它登录的两端流程

注册阶段的密钥建立

注册阶段的密钥建立

上一关你已经知道:Passkey 用的是「公钥挂锁 + 私钥钥匙」这套机制。但这套东西不是一注册就凭空冒出来的——它需要用户和服务器「约定」一下。这一关我们就走一遍这个约定过程。

一、起点:用户点一下「启用 Passkey」

你第一次在某个网站(比如 Gmail、GitHub)登录后,账号设置里会看到「启用 Passkey」或「添加通行密钥」的按钮。你点一下,故事就开始了。

**重要前提**:你必须先用自己的「传统方式」登录一次(通常是密码 + 短信/邮箱验证码),证明「这账号是我的」。服务器绝不会在没确认身份的情况下,把公钥绑到一个陌生账号上——否则任何人点启用都能绑,那不乱套了。

二、注册的完整流程

flowchart TD
    A[用户已登录 点启用 Passkey] --> B[服务器生成一段随机挑战]
    B --> C[服务器把挑战发给用户设备]
    C --> D[设备调用安全芯片 生成新密钥对]
    D --> E[私钥存入安全芯片 无法导出]
    D --> F[公钥准备好]
    F --> G[设备用私钥对挑战签名]
    G --> H[公钥和签名结果 回传给服务器]
    H --> I[服务器用公钥验证签名]
    I --> J[验证通过 服务器把公钥存进数据库]
    J --> K[完成 用户从此可以无密码登录]

逐句拆解:

  1. **服务器生成挑战**:服务器临时造一段随机数据(你可以理解成一道「应用题」),目的是让设备当场证明它手里真的有私钥。这道题必须是新的、一次性的——下一节「登录」会再讲为什么。
  1. **设备生成密钥对**:设备(手机/电脑)调用系统级的安全模块(iPhone 的 Secure Enclave、Windows 的 TPM)在硬件里生成一对全新的密钥。这个动作是「当场现造」,不是从云端下载。
  1. **私钥就地封存**:私钥生成的那一刻就被锁进安全芯片的隔离区,操作系统、应用、甚至用户本人都拿不出来、导不出去。它从此就住在这个设备里。
  1. **公钥出门旅行**:公钥连同对挑战的签名(用私钥算出来的)一起打包,发回给服务器。注意:私钥从头到尾没有离开设备,服务器也从未接触过它。
  1. **服务器验签 + 落库**:服务器用刚收到的公钥去验证签名——能验证通过,就证明设备确实持有对应的私钥。然后服务器把「这个账号 ↔ 这把公钥」这个对应关系写进数据库,跟用户名绑定。

三、注册完之后,账号在服务器那边长什么样?

注册前,服务器数据库里你这行是:

| username | password_hash | |----------|---------------| | zhang@example.com | 8f3a2b... |

注册 Passkey 之后,password_hash 那列通常还在(很多网站仍保留作为兜底登录方式),但多了一行 Passkey 记录:

| username | public_key | created_at | |----------|-----------|------------| | zhang@example.com | 04a7c9... | 2024-... |

以后你登录时,服务器不再问你密码了——它会用这把公钥去「验签」。这才是真正的「无密码」。

四、域名绑定:注册时就锁死了使用范围

你可能注意到,注册时服务器发挑战、收公钥的整个对话,是在一个具体的「域」(比如 `accounts.google.com`)里完成的。这把公钥会被**绑定**到这个域:将来只有真正标着「`accounts.google.com`」的网页才能用这把公钥完成验签。

这是 Passkey 防钓鱼的物理基础——钓鱼站点的域名对不上,服务器根本不认。这一点后面小节会详细讲,但你需要先记住:注册时做的「域名绑定」是后面所有安全保证的地基。

五、一个具体例子:小张在 GitHub 启用 Passkey

整个过程小张需要做的只有两件事:点启用、按指纹。**没有记忆任何密码、没有抄写任何备份码。**

**要点:** 注册 Passkey 的本质是「服务器出一道题、设备当场造一把锁(公钥)和一把钥匙(私钥),只把锁发回去,钥匙自己留着用」——从此登录不再需要密码,因为「证明我是我」的方式从「我说出秘密」变成了「我手里握着钥匙」。

登录阶段的挑战-应答

登录阶段的挑战-应答

上一节咱们走完了注册:你点启用、设备当场造了一把锁(公钥)和一把钥匙(私钥),**只把锁交给服务器,钥匙锁进了你设备的安全芯片里**。这个状态就是登录阶段的起点——服务器手里有公钥,私钥还在你设备里。今天我们就走一遍登录。

一、开场类比:为什么每次都要出新题?

你想象一下演唱会的入口:黄牛把你的票拍照复印了几百张想混进去。如果检票员只认「票面图案」,那复印票照样能进。怎么办?现场**给你的票盖一个当次才有的章**——今天的日期加一段随机乱码——下次演出再盖一个完全不一样的章。黄牛哪怕复制了票面,也复制不了今天的章。

Passkey 登录就是这个思路:**每次登录,服务器都要出一道全新的题(挑战),设备用私钥当场做答。** 这就是「挑战-应答」这个名字的由来。

二、登录的完整流程

flowchart TD
    A[用户打开登录页 选择用 Passkey 登录] --> B[服务器生成一段新挑战]
    B --> C[服务器把挑战发给用户设备]
    C --> D[设备弹窗要求用户验证 指纹/面容/PIN]
    D --> E[私钥被调用 对挑战做签名]
    E --> F[设备把签名结果发回服务器]
    F --> G[服务器用上次存的公钥验证签名]
    G --> H{验证通过}
    H -- 是 --> I[服务器建立会话 用户登录成功]
    H -- 否 --> J[拒绝登录]

逐句拆解:

  1. **服务器出新挑战**:服务器临时造一段随机数据,**和注册时的那道题完全不一样,也和上一次登录时不一样**。每道挑战只能被接受一次,下次登录服务器会再出一道新的。
  1. **设备要用户先验明身份**:设备弹出 Face ID / 指纹 / 设备 PIN 让你确认「是我本人在用」。这一步**不是 Passkey 在验你,是设备在保护私钥不被偷用**——任何人拿了你已经解锁的手机过来,没有你的指纹一样调不动私钥。生物识别过不了,私钥就不会被放出来签名。
  1. **私钥做签名**:你的设备调用安全芯片里的私钥,对那道新挑战做一次数学运算,产出一段「签名结果」。**私钥本身从头到尾没离开设备,出去到网络上的只有签名**。
  1. **服务器验签**:服务器用上次注册时存下来的公钥去验证这段签名。能验证通过,服务器就确信「刚才那个设备确实持有对应的私钥」,而私钥又只有「通过了你设备上的生物识别」才被放行——于是服务器也就间接确认了「操作的人是你本人」。
  1. **建立会话**:验证通过后,服务器生成一段会话凭证(cookie 或 token)写进你的浏览器,之后你带着这个凭证就算「已登录」,后续请求就不用每次都重新验 Passkey 了。

三、为什么这一套比密码安全?

这就是「挑战每次都新」这个设计真正的价值:**让所有旧的应答全部作废,从根本上堵死「截一次反复用」这条路**。

四、具体例子:小张第二次登录 GitHub

整个过程他**没输任何密码、没记任何东西、没有任何秘密在网络上传**。最关键的是——就算有人抓到了这次请求的完整数据,明天他拿这个签名再去,**GitHub 出的题已经换了,对不上**。

**要点:** Passkey 登录的核心是「服务器每登录都出**新题**、设备用私钥**签名作答**、服务器用公钥**验签**」——三步中没有「秘密」在网络上传,旧的应答也因为下次题目不同而作废,从根本上堵死了「截获密码复用」这条路。

同设备登录与跨设备二维码登录

同设备登录与跨设备二维码登录

上一节我们走完了同设备登录的完整流程——服务器出题、设备当场答题、签完名发回去。那是**最常见的情况**:你用自己的手机或自己的电脑登录。但如果换了一台**不是你自己的设备**呢?比如公司公用电脑、朋友家电脑、酒店大堂的展示机——这些设备上根本没你的 Passkey。这一节我们就来看,Passkey 是怎么处理「换设备登录」这件事的。

一、为什么会有两种登录方式?

**类比**:你家钥匙就揣在你身上(你手机的 Passkey 通过 iCloud / Google Password Manager 跟着你走——你之前注册过的那把私钥,云端有一份同步副本,登录时会被按需取回)。日常回家当然是用自己的钥匙开门(**同设备登录**)。但万一你出差到了外地,钥匙没带身上——总不能让酒店前台远程帮你开门吧?得有个**让前台确认「你本人确实在本地」**的办法(**跨设备登录**)。

二、跨设备二维码登录的完整流程

下面是 Passkey 跨设备登录的完整流程。这套流程看起来「多绕了一圈」,但它要解决一个核心难题:**怎么保证「我手机是给眼前这台电脑签的名」,而不是被钓鱼网站诱骗着、给地球另一端某个服务器签的名?**

flowchart TD
    A[小张在公用电脑打开 GitHub 登录页] --> B[GitHub 返回一个新挑战]
    B --> C[电脑把挑战编进一个二维码显示出来]
    C --> D[小张用自己的手机扫描这个二维码]
    D --> E[手机通过蓝牙与电脑建立近场通道]
    E --> F{蓝牙近场验证}
    F -- 验证失败 / 不在物理附近 --> G[拒绝登录]
    F -- 验证通过 --> H[手机从 iCloud 或 Google 同步取出对应 Passkey]
    H --> I[手机弹窗要求小张做生物识别 指纹/面容/PIN]
    I --> J[手机从安全芯片取出私钥 对挑战做签名]
    J --> K[签名通过蓝牙近场通道发回电脑]
    K --> L[电脑把签名转发给服务器]
    L --> M[服务器用注册时存的公钥验签]
    M --> N{验证通过}
    N -- 是 --> O[登录成功 建立会话]
    N -- 否 --> P[拒绝登录]

我们拆开看每一步的关键点:

  1. **电脑显示二维码**:这个二维码里主要包含两样东西——服务器给的那道新挑战,以及**一个用于本次会话的临时数据**。二维码只能被用一次,扫晚了就失效。
  1. **手机扫二维码**:手机上的 Passkey 应用(Apple 密码、Google 密码管理器、1Password 等)启动,读取二维码里的挑战。
  1. **【关键】蓝牙近场通道**:手机和电脑通过蓝牙在**物理上握手**——这一步不是「为了传数据方便」,**是为了让电脑向手机证明「我就是站在你面前的那台电脑」**。如果手机是在地球另一端被远程诱骗的,它根本不可能和这台电脑建立近场蓝牙连接。
  1. **手机从云端取回 Passkey**:因为电脑上没有,手机会从云端同步下来的副本里把对应的私钥按需取回。**取回后只在本机使用,不会「借给」电脑**。
  1. **手机做生物识别 + 私钥签名**:这一步和同设备登录完全一样。指纹/面容/设备 PIN 通过后,安全芯片才放出私钥给挑战做签名。
  1. **签名通过蓝牙近场通道发回电脑**:注意——**签名只回给「刚才跟我蓝牙握手的那台电脑」**,不通过互联网广撒。
  1. **电脑转发签名到服务器**:电脑再把这个签名按正常 HTTP 请求发到服务器。
  1. **服务器验签**:用小张账号下注册时存下来的公钥验证。验证通过,登录成功。

三、为什么必须用蓝牙?只扫个二维码不行吗?

这是这一节最值得记住的一刀。

如果只有「扫个二维码」就完成签名——没有任何近场验证——那么:

这就是所谓的「**远程中继攻击**」:你以为是给面前这台电脑签的名,结果签名漂洋过海到了骗子手里。

**蓝牙近场就是给「签名前必须物理到场」加的一道硬约束**:手机只有在物理上**真的**站在电脑旁边(一般几米之内)才签得了名。这一关把「远程签」这条路从物理层面就堵死了——骗子就算把假登录页做得再逼真,他也没办法在地球另一端跟你的电脑做蓝牙握手。

这就是 FIDO 联盟在设计跨设备流程时坚持要加「本地通道」的原因:**让「操作人就在设备旁边」这件事,从一句口号变成一个可被蓝牙握手验证的事实**。

四、具体例子:小张在公司公用电脑登录 GitHub

哪怕小张旁边有人偷看了全程,也**没有截获任何能复用的东西**——签过的名只对当时那道题有效,下一道题又得新签。

**要点:** 同设备登录是上节讲的本地挑战-应答;跨设备登录则多绕了「电脑显二维码 + 手机扫码 + 蓝牙近场握手 + 手机从云端取 Passkey 签名 + 签名经蓝牙回到电脑」这一圈——其中**蓝牙近场握手是反远程钓鱼的核心**:「必须在物理上靠近」这一条,把「远程诱骗签名」这条路从根上堵死。

![跨设备 Passkey 登录:手机扫码 + 蓝牙近场握手](https://tma-media.oss-cn-beijing.aliyuncs.com/tma/illustrations/b4a4c5fd-001e-47e9-9d1a-5c96f4dd7227.jpg)

Passkey 天然防钓鱼的根源

Passkey 天然防钓鱼的根源

前几节我们讲了 Passkey 是怎么把密码「干掉」的:公私钥对让服务器永远见不到秘密、近场蓝牙把「远程诱骗」堵死。但还有一个最常被拿来质疑的问题没正面回答——**如果用户被骗着去了一个假网站,假网站能不能也走完这套登录流程?** 这一节我们就看 Passkey 是怎么**从流程根上**让钓鱼站根本完不成认证的。

一、先复习:密码为什么挡不住钓鱼?

**类比**:你家门钥匙能开你家——也能开任何一个长得像你家门的假门。**钥匙不挑门**。密码也是这样:你把一串字符敲进一个输入框,浏览器根本不管这个输入框是嵌在真站 `github.com` 里还是嵌在钓鱼站 `github-login.com` 里。字符一离开你的手指、传上网,钓鱼站就拿到了——和你敲进真站时**完全一样的东西**。

钓鱼之所以屡试不爽,根源就一句话:**密码是可重放的、跨域通用的内容**。同样的字符,无论敲到哪个站,效果都一样。

二、Passkey 私钥不挑域吗?——硬挑

Passkey 的私钥当然也是不挑「谁」来请求的——**但它死死地挑「哪个域」来请求**。每个 Passkey 在注册时就被**焊死**了一个域名(技术上叫 RP ID,Relying Party ID),比如 `github.com`。这个绑定是写到 WebAuthn 协议里的、由浏览器和操作系统在底层强制执行的一条规则:

这不是弹个警告让你「自己小心」——是**流程层面就跑不下去**。钓鱼站连触发「指纹验证→私钥签」这个环节的资格都拿不到。

三、对比一下:传统 2FA 为什么还是会被钓?

你可能想:现在很多网站不是有短信验证码、Authenticator 一次性口令吗?这些不也是「一次性」的?为啥还会被骗?

因为 2FA 的**那一道额外验证**还是发生在钓鱼站这一侧的——钓鱼站照样能在用户输入 2FA 码的瞬间把码抓走,再**实时转发**到真站去(所谓「中继攻击」)。2FA 增加的只是攻击者多了一道要绕的坎,**不是从根上切断了可能性**。

Passkey 完全不同:钓鱼站**拿不到任何可重放的东西**。私钥在安全芯片里、不出来;签名是「对当前这道挑战」的,离了这道挑战就作废;更要命的是——**根本不会签**——因为域名对不上。

四、流程图:钓鱼站走到哪一步被卡住

flowchart TD
    A[用户被骗到 fake-github.com] --> B[钓鱼站要求 Passkey 登录]
    B --> C[浏览器读取用户设备上的 Passkey 列表]
    C --> D{列表里有 fake-github.com 的 Passkey 吗}
    D -- 没有 --> E[浏览器直接报错 此站无 Passkey 可用]
    D -- 有 github.com 的 Passkey --> F[浏览器检查 Passkey 绑定的域名 github.com]
    F -- 与当前页域名不一致 --> G[安全芯片物理层拒绝签名]
    G --> H[根本不弹生物识别验证 流程直接中断]
    H --> I[钓鱼失败 用户没输入任何东西 没泄露任何东西]
    F -- 域名一致 github.com --> J[正常流程 弹出生物识别]
    J --> K[用户做指纹或面容验证]
    K --> L[安全芯片释放私钥并签名]
    L --> M[登录成功]

注意左下角那条**根本走不到**的路径:哪怕你手机上恰好存着 `github.com` 的 Passkey,钓鱼站也休想让它吐出来——**安全芯片在硬件层就拦掉了**。

五、具体例子

对比一下:如果小张用的是密码 + 2FA 短信码,他**很可能**会乖乖把密码敲进钓鱼站、再把收到的短信码也输进去——然后**就完了**。Passkey 把「被骗着把钥匙交出去」这件事,从「需要靠用户自己警惕」,变成「**根本做不到**」。

**要点:** Passkey 抗钓鱼的根源不是「多了一道验证」——而是**私钥在硬件层被绑死在注册时的域名上**。钓鱼站永远拿不到这个私钥的「使用权」:浏览器和操作系统**在协议层**就拒绝了跨域签名请求,**根本走不到让用户做生物识别那一步**。这不是「警告用户小心」——是「这条路物理上就不通」。

学习笔记

注册与登录的完整流程

一、注册阶段:公钥的建立与落库

**前提**:必须先用传统方式(密码 + 短信/邮箱验证码)登录一次,证明账号归属,服务器才会为该账号绑定 Passkey。

**流程要点**:

  1. 服务器临时生成一段随机挑战发给用户设备
  2. 设备调用系统级安全模块(iPhone 的 Secure Enclave、Windows 的 TPM)当场生成全新的密钥对
  3. 私钥就地封存在安全芯片的隔离区,操作系统、应用、用户本人都无法导出
  4. 公钥连同对挑战的签名一起回传给服务器;私钥从头到尾不离开设备
  5. 服务器用公钥验签通过后,将「账号 ↔ 公钥」对应关系写进数据库

**注册前后数据库对比**:

| 阶段 | username | password_hash | public_key | |------|----------|---------------|------------| | 注册前 | zhang@example.com | 8f3a2b... | — | | 注册后 | zhang@example.com | 8f3a2b...(通常保留作兜底) | 04a7c9... |

**域名绑定**:注册时这把公钥会被绑定到具体域(如 `accounts.google.com`),由 WebAuthn 协议底层强制执行,未来只能在该域使用。

二、登录阶段:挑战-应答机制

**核心思路**:服务器每次登录都出一道全新的一次性挑战,设备用私钥当场作答,旧应答自动作废。

**流程要点**:

  1. 服务器生成新挑战(与注册时、上次登录时都不同,每道只接受一次)
  2. 设备先弹出生物识别(Face ID/指纹/PIN)——这是设备在保护私钥不被偷用,不是 Passkey 在验身份
  3. 私钥被调用对挑战做签名,产出一段签名结果
  4. 设备把签名发回服务器,私钥不出设备
  5. 服务器用注册时存的公钥验证签名,通过则生成会话凭证(cookie/token)建立登录态

**为什么比密码安全**:

三、同设备登录 vs 跨设备登录

**同设备登录**:本地就存着 Passkey,整个挑战-应答在本机闭门完成,快且无感。

**跨设备二维码登录**(登录设备上没有 Passkey,用身边带 Passkey 的手机远程答题):

  1. 电脑显示二维码,内含服务器新挑战和本次会话临时数据(二维码一次有效)
  2. 手机扫码读取挑战
  3. 关键步骤:手机与电脑通过蓝牙建立近场通道,证明「我就是站在你面前的那台电脑」,堵死远程诱骗
  4. 蓝牙验证通过后,手机从云端(iCloud/Google Password Manager)同步副本按需取回 Passkey
  5. 手机弹生物识别 → 安全芯片取出私钥对挑战签名
  6. 签名通过蓝牙近场通道回给电脑,电脑转发服务器,服务器用公钥验签

**核心差异**:跨设备多出的「蓝牙近场」不是为传数据方便,而是为让手机确认眼前这台电脑在物理附近。

四、Passkey 天然防钓鱼的根源

**密码为何挡不住钓鱼**:密码是可重放的、跨域通用的内容,浏览器不管输入框在真站还是钓鱼站,字符传上网钓鱼站就拿到,与敲进真站完全一样。

**Passkey 的硬挑域机制**:

**对比 2FA 的不足**:2FA 的额外验证仍发生在钓鱼站一侧,钓鱼站可实时把验证码转发到真站(中间人/中继攻击),只是增加一道坎,未切断可能性。Passkey 则让钓鱼站根本拿不到任何可重放的东西。

**钓鱼站被卡死的路径**:用户在假站发起 Passkey 登录 → 浏览器读取 Passkey 列表 → 检查绑定域名与当前页域名 → 不一致 → 安全芯片物理层拒绝签名 → 不弹生物识别 → 流程中断,用户未输入任何东西。

第 5 关 · FIDO2 / WebAuthn 标准各司其职

能说清 FIDO2、WebAuthn、CTAP2 三个词的关系,以及为什么需要它们

FIDO Alliance 与 FIDO2 的定位

想象你从国外带回一台笔记本,回国想插电——发现插头根本插不进墙。各国早期都自己定电源标准,结果就是「我的设备到别国就不能用」。Passkey 早几年也有同样的「标准混乱」问题。

早期的标准乱局

2012 年之前,业界并没有统一的「在线身份验证」标准:Google 有自己的 Titan Key 体系,微软有 Windows Hello,银行的 U 盾又是另一套独立协议。各家网站要适配各种设备,工程师累,用户也搞不清「我手里这个 U 盾到底能不能登那个网站」。这就是 FIDO Alliance 想终结的局面。

FIDO Alliance:制定标准的那个组织

FIDO Alliance(FIDO 联盟)成立于 2012 年,由 PayPal、联想、Nok Nok Labs 等公司联合发起。「FIDO」全称 Fast Identity Online,意思是「快速在线身份」。

现在联盟成员已扩展到几百家:Google、Apple、Microsoft、Meta、Amazon、三星、华为、Yubico、Intel、Visa、Mastercard 等几乎所有大厂都在里面。这个阵容解释了为什么 Passkey 能跨平台、跨浏览器铺开——**标准是大家共同制定的,谁都没动力去另起炉灶**。

类比:FIDO Alliance 就像制定 USB 接口标准的那个组织——它不生产 U 盘,只规定「接口长什么样、协议怎么走」。各家公司按这个规格做,全世界的 U 盘和电脑就能互通。

FIDO2:不是一项规范,是一组规范

这里有个特别容易踩的坑:「FIDO2」**不是**单一技术规范,而是**一组规范的统称**。它核心包含两个部分:

flowchart TD
    A[FIDO2 规范族] --> B[WebAuthn]
    A --> C[CTAP2]
    B --> D[W3C 制定<br/>网页 API]
    C --> E[FIDO Alliance 制定<br/>设备协议]
    D --> F[网站 ↔ 浏览器]
    E --> G[浏览器 ↔ 硬件设备]

WebAuthn 和 CTAP2 各管一端、互相配合——具体怎么配合,留到下一块再展开。

这套标准到底要解决什么问题

回到本质:FIDO2 解决的是「**让任何支持它的网站,能用任何支持它的设备完成安全登录**」。

打个比方:WebAuthn 像是「墙上插座」的规格,CTAP2 像是「电器插头」的规格。两边都按 FIDO2 来,全世界的电器和墙就能互通。

没有这套标准之前,你可能遇到过这种尴尬:某银行 App 只认它自家发的 U 盾,换个品牌就报错;某网站只支持 Chrome 不支持 Safari——这些都是「标准没统一」的副作用。FIDO2 出现后,这类问题大幅减少:你 iCloud 钥匙串里存的 Passkey,可以在 Chrome 里用、也可以在 Edge 里用;Google 的 Passkey 可以在 iPhone 上用、也可以在 Windows PC 上用。

要点

FIDO Alliance 是制定 Passkey 标准的国际组织;FIDO2 是它推出的一组规范族,核心由 WebAuthn(W3C 制定的网页 API)和 CTAP2(FIDO Alliance 制定的设备协议)构成。这套标准的存在,让「任何网站 × 任何设备」都能跑通 Passkey 流程。

WebAuthn:网页认证的标准 API

想象你到一家餐厅点菜。服务员(网站)不能直接钻进后厨(硬件设备)炒菜,它得先把订单递给前台(浏览器),由前台去协调后厨。WebAuthn 就是规定「服务员和前台之间怎么下单、怎么接菜」的那张标准流程单。

WebAuthn 是什么、归谁管

WebAuthn 全称 Web Authentication,是 W3C 制定的网页 API 标准。W3C 就是制定 HTML、CSS、HTTP 那些标准的同一批人——他们是网页世界的「基础建设部」。WebAuthn 这个标准在 2019 年正式成为 W3C 推荐标准,目前所有现代浏览器(Chrome、Safari、Edge、Firefox)都支持。

它要解决的核心问题很具体:**让任何一个网站,都能用同一种「说法」去跟浏览器要「帮我做一次 Passkey 操作」**。

它规定的是哪两边

回到上一节的插头插座比喻:

也就是说,**WebAuthn 是网站和浏览器之间的 API 接口标准**,不是网站和硬件设备直接对话。

一次 Passkey 流程,网站到底在调什么

WebAuthn 定义了两大类调用动作:

  1. **「注册一个新钥匙」**:网站告诉浏览器「我需要为这个用户生成一对新钥匙」;浏览器协调硬件生成公私钥,把公钥和凭证 ID 交给网站存进数据库。
  2. **「用现有钥匙登录」**:网站告诉浏览器「我需要这个用户证明他是本人」;浏览器协调硬件完成签名验证,把结果交给网站。

整个过程对网站来说就像调一个函数:「给我注册」或「给我登录」——背后浏览器跟手机、U 盾、指纹器怎么谈,那是另一回事。

在这条链路上,流动的是什么

网站通过 WebAuthn 发给浏览器的,是一段「挑战数据」(一段随机字符串)。浏览器让硬件用它手里的私钥对这段字符串做签名,再把签名结果交回网站。网站用之前存下来的公钥去验签:对上了,就是本人;对不上,拒绝。

flowchart LR
    A[网站] -->|1. 发起登录请求 附带随机挑战| B[浏览器]
    B -->|2. 用私钥签这段| C[硬件设备]
    C -->|3. 返回签名| B
    B -->|4. 把签名交给网站| A
    A -->|5. 用存的公钥验签| A

注意:整个过程里,**私钥从头到尾没出过硬件设备**。网站拿到的只是「签名结果」和「公钥」,任何中间环节都偷不走私钥。

网站这一边要存什么

WebAuthn 规定网站在注册后必须保存两样东西:

除此之外网站不需要存任何敏感信息——这一点和传统密码系统差别巨大:以前要小心存密码哈希、防脱库;现在公钥本身泄露了也没用,没有私钥签不出有效签名。

为什么这套标准对用户意味着「通用」

因为 WebAuthn 是 W3C 标准,所有现代浏览器都支持;只要网站按它开发,不用管用户用的是哪台设备。所以你在 Safari 里存的 Passkey,理论上也能在 Chrome 里调出来用——浏览器之间会通过 iCloud 钥匙串、Google 密码管理器等方式同步。这套标准打通了「网站 ↔ 浏览器」这一头,再加上 CTAP2 打通「浏览器 ↔ 设备」那一头,Passkey 跨设备跨浏览器的体验才成为可能。

要点

WebAuthn 是 W3C 制定的网页 API 标准,规定「网站 ↔ 浏览器」之间怎么发起 Passkey 流程;网站通过它发起注册或登录请求,浏览器再协调硬件完成私钥签名,私钥永远不出设备。

CTAP2:硬件设备与客户端的桥梁

设想这样一个场景:你坐在咖啡馆,笔记本没装指纹器,却想登录公司后台。笔记本说「我手头没有能签名的设备」,但你手机里有 Passkey。这中间就需要一种「隔着两台设备也能让它们安全对话」的语言——这就是 CTAP2 要解决的问题。

CTAP2 是什么、归谁管

CTAP2 全称 Client to Authenticator Protocol 2(客户端到认证器协议第二版)。它跟 WebAuthn 是**两个不同组织**定的标准:

两者刚好首尾相接:网站通过 WebAuthn 把指令交给浏览器,浏览器再通过 CTAP2 把指令转交给硬件设备;硬件设备的结果也按相反路径返回。

它的核心任务:让客户端找得到设备、说得上话

CTAP2 解决三个具体问题:

  1. **连接**:客户端怎么发现、连上一台硬件设备?
  2. **传达**:把「请用你的私钥对这段挑战做签名」这个请求传给设备?
  3. **回报**:把设备的响应(签名结果、用户是否在场、设备信息)带回客户端?

这三个问题在过去各自独立——不同厂商、不同设备有不同的私有协议。CTAP2 出现后,**只要设备和客户端都支持 CTAP2,就能互通**。这就是为什么一个 YubiKey(一种 U 盾形态的硬件钥匙)能在 Chrome、Edge、Firefox 上都能用。

三种传输通道:USB、NFC、BLE

CTAP2 定义了三种「物理运输方式」,让客户端能跟设备连上:

不同场景用不同通道,但**协议本身是统一的**——这就像快递有陆运、海运、空运,但运单格式全国统一。

「跨设备登录」是这个标准的看家本领

CTAP2 真正让人惊艳的是它支持一种叫 **hybrid transport**(混合传输)的模式。这个模式下,笔记本和手机可以**用不同的传输方式**完成对话:

为什么这种场景重要?因为你可能**正在登录的设备里根本没有私钥**——很多公司只允许员工在自己手机里存 Passkey,但日常在笔记本上办公。这种「手机当钥匙、笔记本当门」的模式过去没有统一协议,是 CTAP2 把它标准化了。

flowchart LR
    A[笔记本浏览器] -->|1. 通过 WebAuthn 发起登录| B[笔记本操作系统]
    B -->|2. 通过 CTAP2 over BLE| C[手机]
    C -->|3. 用户在手机上确认| C
    C -->|4. 私钥签名 返回结果| B
    B -->|5. 把结果交给网站| A

注意这条链路上,**私钥始终在手机里**——笔记本从头到尾没碰过私钥,只负责把网站和手机「接上线」。

设备里有什么:认证器的内部构成

一个支持 CTAP2 的「认证器」(authenticator)通常包含几样东西:

这三样东西可以都在一颗专用的安全芯片里(手机里的 Secure Enclave、笔记本里的 TPM、专门的 U 盾),也可以分布在多个组件里。但 CTAP2 不关心**怎么实现**——它只规定「外面看到的协议接口长什么样」。这给厂商留了实现空间。

CTAP2 和 WebAuthn:一张表看清分工

把前两节拼起来看,完整的 Passkey 流程跨越了两个标准:

| 段落 | 标准 | 负责方 | |------|------|--------| | 网站告诉浏览器「我需要认证」 | WebAuthn | 网站 ↔ 浏览器 | | 浏览器找设备、让设备签名 | CTAP2 | 浏览器 ↔ 硬件设备 | | 设备把签名结果返回 | CTAP2 | 硬件设备 ↔ 浏览器 | | 浏览器把结果交给网站 | WebAuthn | 浏览器 ↔ 网站 |

**WebAuthn 是「业务接口」,CTAP2 是「设备接口」**——一个是网站对外的服务窗口,一个是设备对外的接入端口。两者合起来,就是 FIDO2 这套规范族。

要点

CTAP2 是 FIDO Alliance 制定的客户端与硬件设备之间的通信协议,通过 USB / NFC / BLE 三种通道连接;它让浏览器能在不接触私钥的前提下让设备完成签名操作,并且支持「跨设备」这种笔记本借手机私钥登录的混合传输模式。

一次跨设备登录的完整链路

接着上一节留下的「手机当钥匙、笔记本当门」那个伏笔,把整条链路从头到尾走一遍。

一个具体的场景

市场部的小敏在工位上打开公司后台登录页,网站要求用 Passkey 验证。但她面前这台公司笔记本是统一采购的,没有装指纹模块,Passkey 一直存在她自己的手机里。**「登录的设备」和「拥有私钥的设备」不是同一台**——这种情况在很多公司都常见。CTAP2 的混合传输(hybrid transport)就是为这种场景设计的。

完整链路:八步走完一次登录

**第 1 步:网站发起挑战(WebAuthn 段 ①)** 小敏在浏览器里输入公司邮箱、点「登录」。网站后台收到请求后,**生成一段随机的 challenge**(一段不可预测的随机数,相当于这次登录的「一次性考卷」),连同网站标识(rpId)一起,按 WebAuthn 协议打包成请求,扔回给浏览器。

**第 2 步:浏览器盘点本机设备(WebAuthn 与 CTAP2 的衔接点)** 浏览器拿到请求后要问一句:「我手头有没有能签名的认证器?」它向本机所有认证器挨个问一声(这一步走的是 CTAP2,但因为在同一台机器上,USB / NFC 用不上)。浏览器发现:**本机一个认证器都没有**。

**第 3 步:浏览器决定走混合传输 + 显示二维码** 本机没设备,浏览器改走「混合传输」模式:它在屏幕上**显示一个二维码**。这个二维码里装的是:

**关键点**:二维码里**没有任何密钥**——它只是一张「握手名片」,告诉手机该连哪台笔记本、用什么建立加密通道。

**第 4 步:手机扫码 + 蓝牙握手(CTAP2 over BLE 起点)** 小敏打开手机上的 Passkey 应用,对准屏幕扫码。手机解析二维码后,通过蓝牙找到笔记本(BLE 广播),双方用二维码里那个临时会话密钥建立一个**加密通道**。从这一步起,手机和笔记本的对话就都在 CTAP2 协议里走了。

**第 5 步:手机请求用户在场确认** 手机收到 challenge 后,不能直接签名——它要**确认是小敏本人在操作**。这是 FIDO2 协议铁打的规矩:私钥可以自动跑,但**每次签名必须经过用户确认**(指纹 / Face ID / PIN 任选一种)。小敏在手机上按一下指纹。

**第 6 步:手机用私钥签名** 指纹通过后,手机里的安全芯片取出私钥,对 challenge 做签名。**这是整条链路最核心的一步**——签名发生在手机里,私钥从出门起就没离开过安全芯片,笔记本从头到尾没碰过。

**第 7 步:签名经 BLE 返回笔记本(CTAP2 over BLE 终点)** 签名结果通过刚才那条加密 BLE 通道回到笔记本浏览器。

**第 8 步:浏览器把响应交给网站(WebAuthn 段 ②)** 浏览器把签名结果、用户在场凭证、设备信息等,按 WebAuthn 协议打包成响应,发回网站。网站用当初注册时存下来的公钥验证签名——验签通过,登录成功。

flowchart LR
    A[网站服务器] -->|1. WebAuthn 含 challenge| B[笔记本浏览器]
    B -->|2. 显示二维码| C[屏幕二维码]
    C -->|3. 扫码 + BLE 握手| D[手机 Passkey 应用]
    D -->|4. CTAP2 BLE 加密通道| B
    B -->|5. CTAP2 发 challenge| D
    D -->|6. 指纹确认 + 私钥签名| D
    D -->|7. CTAP2 返回签名| B
    B -->|8. WebAuthn 响应回网站| A
    A -->|9. 公钥验签 登录成功| A

两个标准的接力点在哪

从上面八步可以清楚看到,**WebAuthn 和 CTAP2 是一场接力赛**:

三个反直觉的细节

走完这条链路后,有几个细节值得拎出来强调:

  1. **私钥从未离开手机**——哪怕经过扫码、蓝牙、笔记本,私钥始终躺在手机的安全芯片里,外部任何环节都拿不到它的原文
  2. **二维码里没有密钥**——它只是「让手机知道该连哪台笔记本、用什么密钥建立加密通道」,里面装的是连接信息,不是签名能力
  3. **每次签名都强制要求用户在场**——哪怕流程全自动,每次都要按一次指纹或输一次 PIN 码,这是协议层铁律,不是某个 App 的安全策略

要点

一次跨设备登录可以浓缩成一条九步链路:网站 WebAuthn 发挑战 → 浏览器发现本机没设备显示二维码 → 手机扫码通过 BLE 用 CTAP2 拿到 challenge → 指纹确认后私钥在手机里签名 → 签名沿 CTAP2 经 BLE 回传 → 浏览器用 WebAuthn 把响应交给网站 → 网站用公钥验签成功。**WebAuthn 负责业务对话,CTAP2 负责设备对话,两者通过二维码 + BLE 完成接力**。

学习笔记

FIDO2 / WebAuthn 标准各司其职

FIDO Alliance 与 FIDO2 的定位

FIDO2 是一组规范

FIDO2 不是单一技术,而是规范族,核心由两部分组成:

| 规范 | 制定方 | 管辖范围 | |---|---|---| | WebAuthn | W3C | 网站 ↔ 浏览器 的网页 API | | CTAP2 | FIDO Alliance | 浏览器 / 操作系统 ↔ 硬件设备 的设备协议 |

WebAuthn:网页认证的标准 API

两类调用动作
  1. 注册新钥匙:网站 → 浏览器 → 硬件生成公私钥 → 公钥与凭证 ID 交回网站入库。
  2. 用现有钥匙登录:网站 → 浏览器 → 硬件签名 → 结果回网站验签。
数据流与隐私边界
网站需保存的内容

CTAP2:硬件设备与客户端的桥梁

三大核心任务
  1. 连接:客户端发现并连上硬件设备。
  2. 传达:把「用私钥对 challenge 签名」请求传给设备。
  3. 回报:把签名结果、用户在场信息、设备信息带回客户端。
三种物理传输通道
跨设备登录:hybrid transport
认证器(authenticator)内部构成

一次跨设备登录的完整链路(八步)

以「公司笔记本无指纹器、Passkey 在自己手机」为例:

  1. **WebAuthn 段①**:网站生成随机 challenge,连同 rpId 打包按 WebAuthn 发给浏览器。
  2. **衔接点**:浏览器盘点本机认证器,发现一个都没有。
  3. 浏览器改走 hybrid transport,**屏幕显示二维码**,内含:BLE 配对临时会话密钥、challenge、网站标识与交易信息、笔记本 BLE 广播标识——二维码中**不含任何密钥**,仅是「握手名片」。
  4. **CTAP2 over BLE 起点**:手机扫码,解析后通过蓝牙找到笔记本,双方用临时会话密钥建立加密通道,此后的对话走 CTAP2。
  5. **用户在场确认**:手机不能直接签名,须先让用户用指纹 / Face ID / PIN 确认。
  6. **私钥签名**:安全芯片取出私钥,对 challenge 签名;私钥自始未离开过安全芯片,笔记本未碰过。
  7. **CTAP2 over BLE 终点**:签名结果经加密 BLE 通道返回笔记本浏览器。
  8. **WebAuthn 段②**:浏览器把签名结果、用户在场凭证、设备信息按 WebAuthn 打包发回网站,网站用注册时存的公钥验签通过,登录成功。

全局要点

第 6 关 · 跨设备同步与设备丢失

讲清 Passkey 在新设备、丢失设备等现实场景下是怎么被找回的,以及 device-bound vs synced 的取舍

为什么要做跨设备同步

为什么要做跨设备同步

想象一个场景:上周你刚换了新手机,把旧手机上的数据迁移过来,数据线一插,通讯录、微信聊天记录、照片都搬过来了——一切照旧。

但是,如果你同时在用 Passkey 登录某个重要账号(比如工作邮箱、银行 App),而这个 Passkey 是「绑死」在旧手机上的——恭喜,新手机上你登不进去。

这就是这一节要讲的:**Passkey 必须在多设备之间能被找到、能被用到**。否则,对绝大多数人就是一场灾难。

一、现实生活里,哪些场景会逼你换「主设备」?

这些不是冷门情况,是几乎每个人都会遇到的:

  1. **换新手机**:苹果每年出新机、安卓厂商半年一旗舰,旧机出二手或回收是常态。手机迁移工具能搬照片、搬 App,但搬不走「锁死」在某台设备上的密钥。
  2. **换电脑**:公司发新电脑、个人从 Windows 换 Mac、买第二台笔记本做差旅或办公用——新电脑第一次登录任何账号,都是「裸奔」状态。
  3. **手机丢了或坏了**:屏幕碎、主板烧、被偷——这不是「会不会」的问题,是「早晚」的问题。一部手机平均寿命 2-3 年。
  4. **清浏览器数据 / 换浏览器**:Chrome 同步没开、误点「清除所有 Cookie 和缓存」、从 Chrome 切到 Edge 或 Safari——这些操作在密码时代只是要重新输密码;在 Passkey 时代,如果密钥只存在本地浏览器配置目录里,就等于密钥被一起清掉了。
  5. **多设备日常使用**:iPhone 通勤看邮件、MacBook 办公室处理文档、iPad 出差路上轻办公——人不会只用一台设备。

二、什么叫「设备绑死」(device-bound)?

直白讲:**Passkey 只能在一台特定设备上使用,换到别的地方就用不了**。

在 FIDO 规范里,这叫 device-bound credential。听起来很安全(「密钥从不离开那台设备,绝不可能被偷」),但代价也是结构性的:

flowchart TD
    A[设备绑死的 Passkey] --> B[换新手机]
    A --> C[手机丢失或损坏]
    A --> D[换电脑]
    A --> E[清浏览器缓存]
    A --> F[想在第二台设备登录]
    B --> G[密钥跟着旧机走]
    C --> G
    D --> G
    E --> G
    F --> G
    G --> H[登不进去 重新注册噩梦]

**比喻**:这就像你给自家大门配了一把「只能装在一扇特定门上的锁」——那扇门拆了,锁就成废铁;想从后门进?对不起,那把锁不认你的后门。

三、安全和方便不是对立的,但需要聪明的设计

听到这里你可能担心:密钥放在云端同步会不会更危险?万一云端被攻破呢?

这个担心是合理的,也是接下来几节要解决的核心问题。但这一节先建立一个认知框架:

这一节只立靶子:**设备绑死对普通人不现实**。后面几节会讲 FIDO 规范里对「绑死」和「可同步」两种模式的官方区分,以及苹果、谷歌等主流厂商怎么在「同步」这条路上各自落子。

**要点:** 现实中几乎每个人都会换手机、换电脑、丢设备、清缓存——任何「密钥只认一台设备」的方案,对普通用户都是不可用的;Passkey 要真正替代密码,必须解决「换设备后还能正常登录」这个基本问题。

两种底层模式:device-bound 与 synced

两种底层模式:device-bound 与 synced

上一节我们发现:Passkey 不能「绑死」在一台设备上,否则换手机、丢手机就成了灾难。但钥匙要在多设备间流通,安全怎么保证?

FIDO 联盟(FIDO2/WebAuthn 标准的制定者)在规范层面就给出了两种官方模式,作为所有厂商(苹果、谷歌、微软、安全硬件厂商)做产品的脚手架。它们分别叫 **device-bound credential** 和 **synced credential**。

一、Device-bound:钥匙永远不出那台设备

直白讲:**私钥生成在哪台设备,就一辈子待在那台设备**,从不上传、不同步。

**代价**:那台设备坏了、丢了、被偷 → 私钥跟着完蛋。你要么有备用设备(再注册一个 Passkey),要么走网站的账号恢复流程(短信验证、身份核身、客服申诉……每家规则都不一样)。

二、Synced:私钥加密后跟着你在多设备间走

另一种思路:**私钥生成后加密存到云端,自动同步到你名下的所有设备**。

**代价**:云端那一份加密私钥的强度,就是整个安全模型的强度。一旦云端加密被攻破(理论极小概率),所有同步过的设备都受影响。但只要端到端加密做得到位,这个风险接近于零。

三、官方对比一览

| 维度 | Device-bound | Synced | |---|---|---| | 私钥存放 | 只在原设备 | 加密后存云端,并同步到多设备 | | 换设备能否登录 | 不能(必须重新注册或走恢复) | 可以(在任意已登录同一账号的设备上登录) | | 设备丢失后果 | 私钥永久丢失 | 登录云端账号即可在新设备恢复 | | 典型代表 | YubiKey、Windows Hello | iCloud Keychain、Google Password Manager | | 主要使用者 | 企业、高安全需求人员 | 普通消费者 |

flowchart TD
    A[网站注册 Passkey] --> B{底层模式}
    B -->|device-bound| C[私钥锁在原设备<br/>如 TPM 或安全密钥]
    B -->|synced| D[私钥端到端加密后<br/>上传到云端同步]
    C --> E[只能用原设备]
    C --> F[设备坏等于密钥亡]
    D --> G[所有登录设备都能用]
    D --> H[设备丢可从云端恢复]

四、一个具体例子帮你感受差异

假设你在某个重要网站(比如工作邮箱)注册了 Passkey:

两种模式没有绝对好坏,**FIDO 规范同时承认这两条路**,让不同安全等级的用户自己选。

**要点:** FIDO 规范里,device-bound 是「私钥钉死在原设备」,synced 是「私钥加密后在多设备间同步」——前者极致安全但绑定硬件,后者便捷但依赖云端加密强度;这两种模式的取舍,正是后续各家厂商方案差异的根源。

iCloud Keychain 同步方案

iCloud Keychain 同步方案

上一节我们把 FIDO 规范的两种底层模式拆开了。这一节我们看第一种落地:**苹果怎么做**。

如果你用过 iPhone 记密码,会发现 Safari 里保存的密码会自动出现在 MacBook、iPad 上——iCloud Keychain 就是背后那只「无形的手」。Passkey 也借用了同一套基础设施。

一、本质:一台设备创建,全家桶都能用

苹果用户在 iPhone 上用 Safari 注册了某个网站的 Passkey,几秒之后,登录同一 Apple ID 的 MacBook、iPad 都会自动出现这个 Passkey——用户什么都不用做。

这套体系建立在三件事上:

二、端到端加密具体怎么落地

你之前学过 E2E 加密的概念,这里看苹果的具体实现:

  1. iPhone 在注册 Passkey 时,私钥在本地出生
  2. iPhone 用自己的设备密钥给私钥加密
  3. 加密后的密文通过 iCloud 上传到云端
  4. 你的其他设备(MacBook、iPad)收到密文后,用各自的设备密钥「协同解锁」

关键点:苹果公司的服务器上只有密文,**理论上连苹果自己都看不到明文私钥**。

但这里有一个重要分支:

普通用户绝大多数都是默认状态。真正在意隐私的人会手动去设置里打开 ADP。

三、谁能看到密钥?一张表说清

| 模式 | 你能看到 | 苹果(理论上)能看到 | 苹果(实际上)能看到 | |---|---|---|---| | 默认 | ✅ | ✅ | ❌(政策禁止) | | 开启 ADP 后 | ✅ | ❌ | ❌ |

四、设备丢了怎么办?四种恢复机制

iCloud Keychain 最被人低估的部分是它的恢复体系——苹果塞了**四把「备用钥匙」**,防止你被自己的设备锁死:

  1. **iCloud 安全码**:注册 Keychain 时设的密码(6 位数字或更长字母数字),用于在新设备首次同步时「批准」钥匙流入
  2. **账户恢复联系人**:iOS 15 后引入,可以指定一个或多个可信的家人/朋友,他们的设备能生成恢复码发给你
  3. **恢复密钥**:一串 28 字符的字母数字组合,建议你抄在纸上、放在保险箱里
  4. **可信设备批准**:新设备加入时,你已有的设备会弹窗「是否允许此设备访问你的钥匙串?」

任何一种机制都足以让你在新设备上恢复全部 Passkey。**这正是 synced 模式相比 device-bound 最大的优势——你永远不会因为丢了某台设备就被锁在外面。**

五、一个具体例子

小王在 iPhone 14 上用 Safari 注册了某银行网站的 Passkey:

整个过程小王只在 MacBook 上做了一次「面容识别」,没有输入任何密码、没收到任何短信。

flowchart LR
    A[iPhone 创建 Passkey] --> B[用本机设备密钥加密私钥]
    B --> C[密文上传 iCloud]
    C --> D[MacBook 拉取密文]
    D --> E[用本机设备密钥解密]
    E --> F[私钥在本地完成签名]
    F --> G[银行验证签名通过]

**要点:** iCloud Keychain 用端到端加密在苹果全家桶间同步 Passkey,私钥在云端始终是密文;它同时提供安全码、恢复联系人、恢复密钥、可信设备四把「备用钥匙」,让 synced 模式下设备丢失不会变成灾难——这是它能给消费级用户安全感的关键设计。

Google Password Manager 同步方案

Google Password Manager 同步方案

上一节我们看了苹果怎么用端到端加密在自家全家桶之间搬运 Passkey。这一节看另一家:Google。**Google Password Manager 是安卓和 Chrome 的内置密码管理器**,从 2024 年开始正式支持 Passkey 同步,它的设计思路和苹果既相似又不同。

一、先建立直觉:苹果的「小圈子」 vs Google 的「开放联盟」

苹果 iCloud Keychain 是个「苹果设备专属小圈子」——iPhone 上注册的 Passkey 只能流转到 iPad、MacBook 这些自家兄弟。

Google Password Manager 更像一个「开放联盟」:安卓手机是主基地,但**只要装了 Chrome 浏览器——Windows 笔记本、Mac、Linux 工作站——登录 Google 账号之后,都能用同一套 Passkey**。这种跨平台能力,是苹果方案做不到的。

二、Google 的同步机制

Passkey 在安卓设备上出生时,私钥被放进一个叫 **TEE(可信执行环境)** 的安全区域(和苹果的 Secure Enclave 是同一类东西,但名字不同)。同步到云端之前,会经历几步:

  1. 私钥在 TEE 里生成,永不离开
  2. 用「屏幕锁派生密钥」对私钥加密——这个密钥来自你设置的 PIN、图案、指纹或人脸
  3. 加密后的密文通过 Google 账号同步到 Google 服务器
  4. 新设备首次同步时:登录 Google 账号 + 在新设备上设置屏幕锁 → 屏幕锁作为「钥匙」解密密文

关键点:**Google 服务器上只有密文,没有明文私钥**——这个等级和苹果「高级数据保护 ADP」开启后相当,比苹果默认等级更严。

flowchart LR
    A[安卓 TEE 生成私钥] --> B[用屏幕锁派生密钥加密]
    B --> C[密文上传 Google 云]
    C --> D[新设备登录 Google 账号]
    D --> E[新设备设置屏幕锁]
    E --> F[屏幕锁派生密钥解密出私钥]
    F --> G[私钥在本地就绪可用]
三、和苹果方案的关键区别

| 维度 | iCloud Keychain | Google Password Manager | |---|---|---| | 跨平台 | 仅苹果设备 | 安卓 + 任何装了 Chrome 的设备 | | 加密依赖 | 每台设备的独立设备密钥 | 用户的屏幕锁 PIN/生物识别 | | 默认隐私等级 | 苹果持备份密钥(开 ADP 后才完全 E2E) | 默认就接近 E2E,Google 看不到 |

**最值得记住的一行**:苹果用「设备密钥」当保险箱锁——每台设备一把,丢了一把不影响其他设备;Google 用「屏幕锁」当锁——所有设备共用一把,一旦泄露风险放大。

四、一个具体例子(synced 模式的典型体验)

小李是 Windows 办公 + 安卓手机的「混合党」:

整个过程小李只用了一次指纹,**手机不在身边、不用掏出、不用蓝牙确认**——因为私钥已经躺在 Windows 端了。这就是 synced 模式的典型体验。

五、补充:什么时候会用到「手机帮忙」?

上例是 synced 模式的正常路径。但有一个例外:**手机没在身边、且 Windows 端还没来得及同步下来 Passkey**(比如新买的电脑刚登录 Google 账号几秒钟)。这时 FIDO2 提供了一种补救机制——hybrid transport(也叫 caBLE 流程):

这套机制**和 synced 模式是两码事**——它本质上是「借手机当一次性 authenticator」,私钥并不会因此常驻 Windows 端。Google Password Manager 同时支持这两种路径:synced 是常态,hybrid transport 是兜底。

六、一个小提醒

Google 方案的便捷性来自「屏幕锁派生密钥」——但这也意味着:**多个设备共用同一把屏幕锁「钥匙」**,屏幕锁一旦泄露,所有设备上的 Passkey 都有风险。日常风险不大,但你心里要有这根弦:屏幕锁 = 你 Passkey 的总钥匙。

下一节我们会看更根本的问题:设备全部丢失时,synced 和 device-bound 两种模式各自的恢复路径和风险。

**要点:** Google Password Manager 用「屏幕锁派生密钥」加密私钥,在安卓+Chrome 跨平台生态里同步 Passkey,默认就接近 E2E;但和苹果每台设备一把锁的设计相比,「统一钥匙」既是便捷的来源,也是风险的来源;hybrid transport 是它为「新设备尚未同步」场景提供的兜底能力。

设备丢失与账号恢复的权衡

到目前为止,我们看过 synced 模式(苹果 iCloud Keychain、Google Password Manager)怎么把 Passkey 同步到多设备。这一节回到一个更现实、也更「疼」的问题:**设备全丢了怎么办?**

用生活类比建立直觉

只有一把家门钥匙——这就是 device-bound:钥匙没了,要么叫锁匠,要么破门,没有第三条路。

家里多配几把钥匙,分散放在父母家、办公室抽屉——这就是 synced:丢一把还有其他副本,但**所有副本都受同一个「母本」保护**——一旦母本失守,所有副本都危险。

两种模式在「设备丢失」下的根本区别

| 场景 | device-bound | synced | |---|---|---| | 丢一台手机 | 其他设备还能用 | 其他设备还能用,新设备也能从云端拉 | | 丢**唯一**设备 | **必须走网站重置**(重新注册 Passkey) | 登录云账号 + 主钥匙,几小时恢复 | | 物理抢手机但没破屏幕锁 | 安全(指纹/人脸对不上) | 同左 | | 全部设备 + 主钥匙都失守 | — | 全部 Passkey 沦陷 |

**关键洞察**:device-bound 把安全感押在「你会妥善保管设备 + 至少留有备用」上;synced 把安全感押在「主钥匙足够强 + 云服务不主动作恶」上。**两种都不是绝对安全**,只是把风险分散到不同地方。

现实中的恢复路径(具体走一遍)

假设手机掉马桶了。

**device-bound 走法**:

  1. 买新手机 → 装银行 App
  2. 银行 App 识别不到旧设备 → 走「找回账号」
  3. 通常需要:身份证 + 人脸识别 + 人工审核
  4. 几天后重新注册一个新 Passkey(旧的已经作废)

**synced 走法**:

  1. 买新手机 → 设置屏幕锁
  2. 登录 Google / Apple 账号
  3. 屏幕锁 PIN 派生的密钥自动解密云端密文
  4. 几小时内所有 Passkey 回到新手机

一个要几天,一个要几小时。

flowchart LR
    subgraph DeviceBound[device-bound 恢复路径]
        A1[丢手机] --> A2[新手机登录网站]
        A2 --> A3[走账号找回流程]
        A3 --> A4[身份证 + 人脸验证]
        A4 --> A5[人工审核 几天]
        A5 --> A6[重新注册 Passkey]
    end
    subgraph Synced[synced 恢复路径]
        B1[丢手机] --> B2[新手机登录云账号]
        B2 --> B3[设置屏幕锁]
        B3 --> B4[主钥匙解密云端密文]
        B4 --> B5[几小时 全部恢复]
    end

一个具体例子

小明 2022 年丢了一次安卓手机,所有账号是 device-bound Passkey:

2024 年又丢了一次。这次所有账号迁到 Google Password Manager(synced):

**两次对比就是核心差异**:device-bound 在关键时刻「卡你一下」换更高安全;synced 让你「丝滑过渡」但把所有鸡蛋放进「主钥匙」这一个篮子里。

synced 模式的命门:主钥匙是单点故障

主钥匙(屏幕锁 PIN、账号密码、主密码)一旦泄露,攻击者就能在新设备上解密出你云端所有 Passkey。

2022 年 LastPass 泄露事件值得记住:黑客拿到的虽然只是加密的保险库,但**主密码弱的用户**最终被暴力破解了。synced 模式把所有设备的安全,都压在了「一个东西」上。

给普通用户的选择建议

**大多数普通用户(95%)**:用 synced 模式(iCloud Keychain 或 Google Password Manager)。理由很简单——丢手机的概率远高于主钥匙被专业黑客盯上的概率,便利性远胜。

**管钱管隐私的重度用户**:在 synced 之外,**给最重要的 1-2 个账号(主邮箱、银行)配一个 FIDO 物理安全密钥**(如 Yubikey,约 200-500 元)。这是 device-bound 的极致形态——密钥在另一个物理设备上,丢手机丢电脑都不影响。

**关键习惯**:

**要点**:device-bound 把安全押在「物理设备在手」上,恢复慢但不怕云端泄露;synced 把安全押在「主钥匙不泄露」上,恢复快但主钥匙一旦失守满盘皆输——普通用户用 synced + 强屏幕锁就够,重度用户在 synced 基础上加一个 FIDO 物理安全密钥作为最后防线。

学习笔记

跨设备同步与设备丢失

现实中几乎每个人都会遇到「换主设备」的场景

现实中几乎每个人都会遇到「换主设备」的场景:换新手机、换电脑、手机丢失或损坏(手机平均寿命 2-3 年)、清浏览器数据或换浏览器、多设备日常使用。

如果 Passkey「绑死」在一台设备上(device-bound),换机、丢机、清缓存都会导致「登不进去、重新注册噩梦」。

「设备绑死」指 Passkey 只能在一台特定设备上使用,换到别处就用不了。其结构性代价是:那台设备坏了,密钥跟着死;换了新手机,得为几十上百个账号重新注册;想在第二台设备登录也不行。

安全与方便不是对立的。完全绑死 = 极致安全但用户体验灾难;完全开放 = 方便但秘密满天飞;真正的好方案是在两者之间找平衡——让密钥能出现在新设备上,但全程加密,连云厂商都看不到。

两种底层模式:device-bound 与 synced

FIDO 联盟在规范层面给出两种官方模式:

flowchart TD
    A[网站注册 Passkey] --> B{底层模式}
    B -->|device-bound| C[私钥锁在原设备<br/>如 TPM 或安全密钥]
    B -->|synced| D[私钥端到端加密后<br/>上传到云端同步]
    C --> E[只能用原设备]
    C --> F[设备坏等于密钥亡]
    D --> G[所有登录设备都能用]
    D --> H[设备丢可从云端恢复]

**Device-bound(设备绑死)**

**Synced(可同步)**

| 维度 | Device-bound | Synced | |---|---|---| | 私钥存放 | 只在原设备 | 加密后存云端并同步 | | 换设备能否登录 | 不能 | 可以 | | 设备丢失后果 | 私钥永久丢失 | 登录云端账号可恢复 | | 典型代表 | YubiKey、Windows Hello | iCloud Keychain、Google Password Manager |

iCloud Keychain 同步方案

本质:一台设备创建,全家桶都能用。Safari 注册的 Passkey 几秒后出现在同一 Apple ID 的其他设备上,用户无需任何操作。

建立在三件事上:

**默认状态 vs 高级数据保护(ADP)**

| 模式 | 你能看到 | 苹果(理论上)能看到 | 苹果(实际上)能看到 | |---|---|---|---| | 默认 | ✅ | ✅ | ❌ | | 开启 ADP 后 | ✅ | ❌ | ❌ |

**四把「备用钥匙」(恢复机制)**

  1. iCloud 安全码:注册 Keychain 时设的密码(6 位数字或更长字母数字),新设备首次同步时「批准」钥匙流入
  2. 账户恢复联系人:iOS 15 后引入,指定可信家人/朋友,他们的设备能生成恢复码
  3. 恢复密钥:28 字符的字母数字组合,建议抄纸放保险箱
  4. 可信设备批准:新设备加入时,已有设备弹窗「是否允许此设备访问?」

任何一种机制都足以让用户在新设备上恢复全部 Passkey——这正是 synced 模式相比 device-bound 最大的优势。

Google Password Manager 同步方案

Google Password Manager 是安卓和 Chrome 的内置密码管理器,从 2024 年开始正式支持 Passkey 同步。

**与苹果的关键区别**

**同步机制**

flowchart LR
    A[安卓 TEE 生成私钥] --> B[用屏幕锁派生密钥加密]
    B --> C[密文上传 Google 云]
    C --> D[新设备登录 Google 账号]
    D --> E[新设备设置屏幕锁]
    E --> F[屏幕锁派生密钥解密出私钥]
    F --> G[私钥在本地就绪可用]
  1. 私钥在 TEE(可信执行环境,与 Secure Enclave 同类)里生成,永不离开
  2. 用「屏幕锁派生密钥」加密私钥——这个密钥来自 PIN、图案、指纹或人脸
  3. 加密后的密文通过 Google 账号同步到 Google 服务器
  4. 新设备首次同步:登录 Google 账号 + 在新设备上设置屏幕锁 → 屏幕锁作为「钥匙」解密密文

**关键点**:Google 服务器上只有密文,没有明文私钥——这个等级和苹果开启 ADP 后相当,比苹果默认等级更严。

| 维度 | iCloud Keychain | Google Password Manager | |---|---|---| | 跨平台 | 仅苹果设备 | 安卓 + 任何装了 Chrome 的设备 | | 加密依赖 | 每台设备的独立设备密钥 | 用户的屏幕锁 PIN/生物识别 | | 默认隐私等级 | 苹果持备份密钥(开 ADP 后才完全 E2E) | 默认就接近 E2E,Google 看不到 |

苹果用「设备密钥」当保险箱锁——每台设备一把,丢了一把不影响其他;Google 用「屏幕锁」当锁——所有设备共用一把,一旦泄露风险放大。

设备丢失与账号恢复的权衡

| 场景 | device-bound | synced | |---|---|---| | 丢一台手机 | 其他设备还能用 | 其他设备还能用,新设备也能从云端拉 | | 丢唯一设备 | 必须走网站重置(重新注册 Passkey) | 登录云账号 + 主钥匙,几小时恢复 | | 物理抢手机但没破屏幕锁 | 安全(指纹/人脸对不上) | 同左 |

第 7 关 · 与其他无密码方案的横向对比

能在和别人讨论时,说清 Passkey 相对短信验证码、魔法链接、社交登录、硬件密钥的独到之处与局限

短信与邮件验证码的软肋

一个直觉:短信验证码是大堂保安替你大声念密码

想象你去银行,保安本该低声确认你的身份,结果他站在大堂中央、用喇叭把验证码和卡号一起喊出来。旁边的人听不清、记不下,但**有组织的窃贼**可以录音、转写、再用专业设备去截。这就是短信验证码的尴尬处境:它被设计成『只有你能收到』,但实际上**发到你手机的那条短信,途中经过的每一站都不对它负责**。

过去十年,行业把短信和邮件验证码当成对抗密码泄露的「救命稻草」——密码丢了没事,还有第二道关。但这道关并不像宣传中那么结实,下面四种攻击都能让它在用户毫无察觉的情况下彻底失效。

一、SIM 卡劫持:让运营商亲手把号码送给攻击者

这是最经典、也是新闻里最常出现的一招。攻击者不需要碰你的手机,只需要给你手机运营商的客服打电话(或在网上伪装),说『我的卡丢了,请把 138xxxx 这个号码转移到我这张新 SIM 上』。客服核对几个基础信息(姓名、身份证号、最近充值金额——这些大多已在别的泄露里流出),核实通过就把号码「过户口」到攻击者的卡上。

从这一刻起,你手机信号消失,攻击者的手机亮起:所有短信验证码、运营商通知全部转到他手里。攻击者用密码重置功能直接登入你的账号,而你的手机安静得像关机一样。

**真实案例**:2019 年 Twitter CEO Jack Dorsey 的账号就是这样被攻破的;2022 年 Uber 攻击事件里,攻击者也是先用 SIM 卡劫持拿到目标的短信,再骗内部员工点钓鱼链接。

二、电信层面的「窃听」:SS7 协议漏洞与伪基站

短信走的是全球电信系统的 SS7 信令网,这个 1975 年设计的协议当时默认「圈内人都是可信的」,因此几乎不验证消息来源。攻击者只要能进入 SS7 网(黑市上有这种服务),就可以**指示运营商把发给某个号码的短信复制一份**到自己的设备,全程不需要碰用户、也不需要骗运营商。

另一种是「IMSI catcher / 伪基站」:在目标附近架设一台伪基站设备,强制手机接入,再把短信拦截下来。警方和情报机构都使用这种技术,黑产手里也有。

**共同点**:用户完全感觉不到攻击发生,验证码就在他眼皮底下被复制走了。

三、邮件账号被破:兜底变成灾难

很多人觉得「短信不安全?那我用邮件验证码」可惜邮件更脆弱。邮件账号的恢复机制是经典的链式设计:忘记密码 → 短信验证 → 找回。但当短信本身被攻破(见上两条),或者邮箱本身的密码就是弱密码、且多处复用(前面模块讲过这是常态),攻击者攻破邮箱后就能:

**邮箱一破,百站沦陷**——因为大多数人把邮箱当成「终极恢复通道」。

四、钓鱼代理(AitM):最狠的一刀——让用户亲手交出两道防线

以上三种攻击都聚焦在『绕过第二因素』。但近两年兴起的一种攻击**同时绕过密码和第二因素**——而且用户全程以为自己操作正确。

它的玩法是这样的:

flowchart LR
    U[受害者] -->|输入账号密码| P[钓鱼代理站]
    P -->|实时转发| R[真网站]
    R -->|发短信验证码给 U| P
    P -->|显示验证码输入框| U
    U -->|把验证码输到假站| P
    P -->|立即转发给真站| R
    R -->|登录成功| P
    P -->|劫持会话| U

攻击者架设一个**实时中转站**(不是静态假页面),受害者点进钓鱼链接后,看到的界面和真网站**几乎一模一样**。当用户输入账号、密码,代理站**立刻**把这些信息原样转发给真网站;真网站按流程给用户手机发短信验证码;代理站再把『请输入验证码』的页面**原封不动**展示给用户。用户把短信里的 6 位数字输进代理站,代理站**毫秒级**转发给真网站——通过验证,登录成功,攻击者拿到会话 cookie,账号易主。

**为什么致命**:用户是**亲手**、**主动**、**完整**地把两道防线(密码 + 实时验证码)都交给了攻击者。任何基于『你知道的』+『你拥有的』的传统两步验证都挡不住这种攻击,因为攻击者把整段对话都中转了,第二因素和第一因素在它手里合流。

这一节讲清了一个关键事实

「双因素认证」听着比单密码安全一倍,但**短信和邮件这两个最普及的第二因素,都不具备抗钓鱼代理的属性**——它们能被实时截获、被运营商错配、被邮件账号连坐。当攻击者站在用户和真网站中间当传话筒时,这两道防线在用户不知情的情况下**同时失效**。

**要点**:第二因素只有**与登录请求本身绑定**(如 Passkey 那种挑战-应答机制),而不是作为独立可中转的「一次性数字」,才能真正对抗实时钓鱼代理攻击——这是下一节讲魔法链接时同样会触及的根本问题。

魔法链接与邮箱即钥匙的边界

一个直觉:把家里所有钥匙都挂在同一把大钥匙上

想象你住在一栋公寓,每天进出用门禁卡。你嫌麻烦,把家里的信箱、保险柜、车库、自行车锁都配了同一把万能钥匙——这一把就能开所有的锁。便利吗?太便利了。但这把钥匙一旦丢了,或者有人复制了一把,你所有的门都同时对外敞开。

「魔法链接」就是这种万能钥匙——只不过这把钥匙住在你的邮箱里。

魔法链接是什么:看似「无密码」的优雅

很多现代产品(Notion、Slack、各种 SaaS 工具)的登录页现在长这样:输入邮箱 → 收件箱里点一个链接 → 直接登录。没有密码要记,没有密码要输,**看着**比密码时代干净很多。

从体验上看,魔法链接做了三件漂亮事:

**但这三件事的「安全」全是表面上的**。

边界一:魔法链接的本质是「把安全托付给邮箱」

魔法链接没有消灭钥匙——它只是把钥匙从「你脑子里的密码」换成了「你收件箱里的链接」。而打开收件箱需要的那把钥匙,是你的邮箱密码(或者邮箱的某种登录方式)。

问题来了:你的邮箱本身是怎么登录的?

flowchart TD
    A[魔法链接登录 Notion] --> B[需要打开邮箱]
    B --> C[邮箱登录方式]
    C --> D{邮箱是怎么保护的}
    D --> E[密码<br/>可能弱 可能复用]
    D --> F[短信验证码<br/>上一节讲的 SIM 劫持]
    D --> G[手机 App 扫码<br/>相对安全但不是人人开]
    E --> H[邮箱被破]
    F --> H
    G --> H
    H --> I[所有用邮箱登录的账号<br/>全部沦陷]

**链式信任的逻辑**:魔法链接的强度 = 邮箱的强度。Notion 没帮你做一道额外的安全门,它只是把门钥匙转交给了 Gmail/Outlook/QQ 邮箱。而**邮箱的安全性,决定了你所有用魔法链接登录的账号的安全性**。

前面模块讲过:大多数人的邮箱密码是**早年注册时设的弱密码**,且**在多个网站复用**。一旦这个邮箱被攻破——

边界二:魔法链接也躲不开钓鱼代理

你以为上一节讲的钓鱼代理(AitM)只能攻破短信验证码?**魔法链接同样会被中转**。

攻击者架设一个假登录页(看起来像 Notion),骗你输入邮箱。你的邮箱收到真链接——但**你不直接点邮件里的链接**。钓鱼代理站会**实时**把链接抠出来,转发给真网站,完成登录,把会话 cookie 抢走。

更狡猾的变种是直接**篡改邮件内容**:攻击者事先已经登录了你的邮箱(通过别的方式破的),看到 Notion 发来的魔法链接,**立刻在另一台设备点了**,不等你反应。

**关键差异**:短信验证码的攻击需要电信级或 SIM 级手段;但魔法链接的攻击**只需要破邮箱**——而破邮箱的方法比破 SIM 卡多得多,也便宜得多。

边界三:邮件服务商自己也会出问题

即使你把邮箱密码设得超强、开了双因素、用了硬件密钥——**邮箱服务本身也可能被攻破**。过去几年里就有攻击者通过攻破第三方邮件服务商的后台,批量盗取邮件的案例。**用户在这一层完全无能为力**:你把安全交给了自己控制不了的第三方。

这正是「中心化信任」的根本问题:当你把所有钥匙挂在邮箱这一把大钥匙上,邮箱服务商的任何一次失误、任何一个内部员工、任何一次供应链攻击,都会直接伤到你。

一个具体场景:魔法链接生态里的「一破百破」

假设你是个市场运营,平时用魔法链接登录 Notion 写文案、用 Slack 沟通、用某看板工具管理项目。

  1. 你某天在一个小网站用邮箱注册了试用账号,密码和邮箱密码**一样**(这是大多数人的习惯)
  2. 那个小网站被攻破,攻击者拿到你的邮箱密码
  3. 攻击者登入你的邮箱
  4. 攻击者去 Notion,点「用邮箱登录」,魔法链接发到你的收件箱
  5. 攻击者**已经在你的邮箱里**,直接点链接,登录成功
  6. 攻击者从 Notion 里翻出你们的客户名单、合同草稿
  7. 顺手再用同样方式登 Slack、看板工具、任何用魔法链接的产品

**从头到尾,你没有输错任何密码、没有泄露任何验证码、没有点任何可疑链接**。攻击者只是借助你已经登录的邮箱,**自己点完了所有魔法链接**。

魔法链接的真正位置

魔法链接不是骗局,它**真的改善了用户体验**——对低风险账号(公开文档、临时试用)来说是个不错的选择。但要清楚它的能力边界:

**这正是 Passkey 要解决的那块拼图**:不再把「安全」托付给任何一把可被复制、可被钓鱼、可被绕过的钥匙,而是让每次登录都做一次**只有你这台设备能完成的数学证明**——后面几节会接着讲推送通知、社交登录、硬件密钥也各有各的局限,到收束那一节我们就能看清 Passkey 为什么是这盘棋里目前最干净的一手。

**要点**:魔法链接的「无密码」只是把密码从产品服务器转嫁到了邮箱——邮箱的强度就是它全部的强度;邮箱被破或被钓鱼,所有用魔法链接的账号在用户毫不知情的情况下一起失守。

推送确认与社交登录的局限

一个直觉:保安代你点头

想象你住的小区请了一位保安,住户名单上只有你一个名字。访客来时,保安给你打电话:「有个穿红衣服的人说找你,让他进吗?」你说「让他进」——保安就开门了。

便利吗?便利。**但你从来没亲眼看过那个红衣服的人**——你只是听到保安描述,然后根据描述决定。

推送确认(Push MFA)就是这种机制:服务器(保安)说「有人要登录」,你的手机弹一条推送,你点「允许」——登录就完成了。**整个过程,服务器做了什么、你点的是什么,全是黑盒**。

推送确认的「服务器信任」陷阱

推送确认通常长这样:输入用户名密码 → 手机弹一条推送「是否允许从 Chrome 在 Windows 登录?」→ 你点「允许」。

它看起来很合理:只有我能在我手机上点啊。但这里有个**关键问题**:你点「允许」的对象,不是「这次登录行为本身」——而是**服务器发过来的那条推送消息**。

服务器为什么发这条推送?**因为它收到了一次用户名密码正确的请求**。但这个「正确」可能来自:

换句话说:**只要攻击者知道你的密码,他就能反复触发推送**——他不需要拿到你的手机,只需要让你**习惯性地点「允许」**。

MFA Fatigue:你烦了,攻击者就赢了

这正是近年最流行的攻击之一——MFA Fatigue(MFA 轰炸)或 Push Bombing。

攻击手法非常直白:

  1. 攻击者已经拿到你的用户名密码(通过撞库或暗网)
  2. 他**不偷**你的手机,也不攻破推送系统
  3. 他**反复**用你的账号密码去触发登录
  4. 你的手机**疯狂震动**:「是否允许登录?」「是否允许登录?」「是否允许登录?」……
  5. 你一开始会点「拒绝」,但推送不停来——凌晨 2 点、午睡时、开会时
  6. 终于有一次,你**条件反射**地点了「允许」——或者你**误以为这是系统消息**点了确认
  7. 攻击者登入
flowchart TD
    A[攻击者拿到你的密码] --> B[用脚本反复触发登录]
    B --> C[服务器每次都发推送]
    C --> D[你的手机被轰炸]
    D --> E{你的反应}
    E -->|一次次拒绝| F[疲劳 烦躁 怀疑系统出 bug]
    E -->|怕错过真消息| G[开始留意推送内容]
    E --> H[某次条件反射点了允许]
    H --> I[攻击者登入]
    F --> I

**真实案例**:2022 年 Uber 的大规模数据泄露,起因就是一名外包员工的手机被 MFA Fatigue 攻击轰炸,攻击者随后在 WhatsApp 上冒充 IT 部门员工,说「刚才那条推送是系统测试,请告诉我你点了几次」——员工信了,把后续验证信息全交了出去。**整个攻击链里,密码学没破一道,技术上没攻破任何东西**——破的是人的耐心和信任。

推送确认的另一个盲区:服务器才是「裁判」

更深层的问题在于:推送确认里,**判断「这次登录是否合法」的,不是你的设备——是服务器**。服务器说「我看到密码对了」,服务器说「我发了推送」,服务器收到「允许」,就开门。

这意味着:

社交登录:把身份外包给 Google 和微信

另一类很常见的「无密码」方案:用 Google/Apple/微信/支付宝账号登录其他网站(OAuth 登录)。点一个按钮,跳到 Google,确认,返回,登入。

它解决了一个真问题:用户不用在每个网站都注册新账号。但它创造了另一个**更大的问题**——**你的身份完全托管给 Google/微信了**。

具体说:

**更微妙的一点**:OAuth 登录的「安全」等于 Google 账号的安全,而 Google 账号本身——还是回到**密码 + 第二因素**那套老问题。Google 帮你做了更强的防护(设备管理、风险评估),但你**无法控制** Google 用什么逻辑判断「这是你本人登录」。Google 的算法认为是你,那就是你;Google 的算法认为不是你——哪怕确实是你,也登不上。

一个具体场景:嵌套账号的雪崩

假设你是市场运营,日常工作用:

  1. 你某天在咖啡馆用公共 WiFi 登录 Google 账号
  2. 有人嗅探到了会话 cookie(公共 WiFi 经典风险)
  3. 攻击者用这个 cookie **直接登入你的 Google 账号**——不需要密码、不需要第二因素
  4. 攻击者去 Slack、Notion、数据看板,**点一下「用 Google 登录」**——全部秒进
  5. 你下班前发现,**一个工作日的所有产出文档**都在攻击者手里

整条攻击链里,**没有一个第三方网站本身被攻破**。破的是 Google 一次,**后面所有网站一起沦陷**——这就是把身份外包的代价。

推送确认与社交登录的真实位置

把这两类方案摆回棋盘:

它们都比纯密码好,但都**没有解决根本问题**:「**证明你是你**」这件事,仍然要依赖某个**外部仲裁者**(服务器、邮箱、Google)来说了算。**Passkey 的革命性就在于——它把「裁判」从服务器手里夺回,交给了你自己手里的设备**。下一节我们就讲,做这件事的最早一波尝试——FIDO U2F 硬件密钥——做了什么、又差在哪里。

**要点**:推送确认的安全取决于服务器推送的「诚意」和你点「允许」的注意力——MFA Fatigue 用耐心击穿警惕;社交登录把身份外包给 Google/微信,账号被破即所有第三方账号同时沦陷。两类方案的共同盲区是:身份判断权不在你手里。

FIDO U2F 硬件密钥与 Passkey 的异同

一个直觉:U2F 就是一把物理钥匙

想象你家门用两把锁:一把普通锁(钥匙藏门垫下),再加一把指纹锁。U2F 就是**那把独立的物理锁**——你得随身带一个 U 盘大小的小设备(YubiKey 这种),登录时插上去「按一下」。

**但注意**——你**还是要输入密码**。U2F 全称叫 Universal 2nd Factor(通用第二因素),关键词是「第二」——它**只是把密码之外再加一道**。

U2F 做对了什么:抗钓鱼的「来源绑定」

U2F 最大的贡献,不是硬件本身——是它**对钓鱼网站天然免疫**。

原理是这样:每次你注册一个网站,U2F 设备为这个网站生成**一对**密钥(公钥私钥),并且——**关键的一步**——这个密钥对**被锁定在那个具体的网站域名上**。

登录时,服务器发来一段「挑战」(随机数),U2F 设备用私钥**对挑战做签名**。这个签名动作有一个硬约束:**只会在请求来自注册时的那个域名时才会执行**。

这意味着:

这就是 WebAuthn/Passkey 沿用至今的「**来源绑定(origin binding)**」机制。即使你**主动**在钓鱼网站输入了用户名、**主动**插上 U2F 设备、**主动**按了一下——私钥就是不配合。

相比之下:

**U2F 是当时唯一扛得住钓鱼的第二因素**。Google 在 2017 年强制全员部署硬件密钥之后,公开的安全简报里提到**公司内部再未发生过针对员工的成功钓鱼事件**——这是后续几年 Google 安全博客里能查到的真实表述。

U2F 没做对的三件事

但 U2F 有一个**非常不市场运营友好**的问题:**它要你随身带个物理小设备**。具体说:

**1. 还是需要密码**——U2F 是「第二因素」,第一因素还是密码。密码的**所有老毛病**(弱密码、撞库、复用)一个不少。U2F 只把攻破成本**抬高了一大截**,但没消灭密码。

**2. 物理设备要随身带**——YubiKey 这种小钥匙容易丢。丢了想登录?没门。除非你提前注册了**多个**备用密钥,并把它们**分散在不同的物理位置**(家里一把、公司一把、家人那里一把)。听起来是不是很烦?

**3. 共享设备用不了**——U2F 设备多半走 USB,但酒店大堂那台公共电脑可能没有可用 USB 口、没有安装驱动或浏览器不支持 U2F 协议;更何况你**根本不想把个人硬件插到一台你不控制的公共电脑上**——你就登不上。

**这三条加起来,U2F 在企业强制配发的场景里行得通**(Google、Facebook 内部就这么用),**但在「让我奶奶也能用」的消费级场景里,几乎推不开**。

Passkey 拿走了什么、留下了什么

Passkey 不是凭空发明的——它**骨子里就是 FIDO2 协议**(FIDO2 = WebAuthn + CTAP2),而 FIDO2 的核心思想、核心密码学、核心的「来源绑定抗钓鱼」机制,**全部继承自 U2F**。

flowchart LR
    A[U2F 2014] -->|仍是第二因素<br>仍需密码+插硬件| B[FIDO2 2018]
    B -->|WebAuthn+CTAP2<br>标准和生态统一| C[Passkey 2022]
    C -->|私钥跟人走<br>无密码+跨设备| D[今天]

Passkey 相对 U2F 做了三件关键的事:

| 维度 | U2F 硬件密钥 | Passkey | |------|------------|---------| | 第一因素 | **还是要密码** | **完全不要密码** | | 私钥存哪 | 独立硬件钥匙 | 你日常用的设备 + iCloud/Google 同步 | | 验证方式 | 插上 + 按一下按钮 | 指纹、面容、屏幕解锁 | | 携带性 | 必须随身带 | 跟着手机走 | | 共享设备 | 几乎用不了 | 扫码就能用(手机当密钥) | | 抗钓鱼 | ✅ 强 | ✅ **同样强**(沿用 origin binding) |

注意**最后一行**——Passkey 抗钓鱼的能力**和 U2F 一模一样**,因为它们是同一套密码学、同一套来源绑定。Passkey 不是发明了新武器,是**把 U2F 的好武器卸下来,搬到了一台不需要密码、不需要携带小设备的现代手机上**。

一个具体场景对比

**用 YubiKey 登录 Gmail**:

  1. 在 Chrome 里输入 `gmail.com`
  2. 输入密码(对,**还要输密码**)
  3. 插上 YubiKey,按一下
  4. 登录成功

**用 Passkey 登录 Gmail**:

  1. 在 Chrome 里输入 `gmail.com`
  2. 弹出系统提示「用面容 ID 登录 Gmail」
  3. 看一眼手机,登录成功

**用 Passkey 在酒店公共电脑登录 Gmail**:

  1. 公共电脑上输入 `gmail.com`
  2. 屏幕显示一个二维码
  3. 你的手机扫码,确认面容
  4. 公共电脑登录成功——**你的密钥**从头到尾**没离开过手机**

**用 YubiKey 在酒店公共电脑登录 Gmail**:

Passkey 也没占到的便宜

U2F 留下来的「**丢失即瘫痪**」问题,Passkey **缓解**但**没彻底解决**:

**加密强度没变,风险点换了位置**。值得指出的是:U2F 时代解决「跨设备可用」基本就是**多买几把 YubiKey 分散保管**(家里、公司各一把),这是用「物理成本 + 收纳麻烦」换安全;Passkey 时代则通过 iCloud Keychain、Google Password Manager 等同步机制,把这个问题转化成了「**你信不信任那个云端账号**」的信任问题。**问题没消失,只是换了形态**——下一节我们就展开讲这些风险是怎么迁移过去的。

**要点**:U2F 用独立硬件钥匙做「第二因素」,抗钓鱼极强但仍要密码、要随身带物理设备、跨设备体验差;Passkey 继承了 U2F 的全部密码学和「来源绑定」抗钓鱼机制,但**把私钥从独立硬件搬到了你日常设备上,并取消了密码这一第一因素**——这是它相对 U2F 的根本进步。

Passkey 自身并非银弹:残留风险

换了更安全的锁,但新的麻烦换了个形态

上一节我们说 Passkey 把 U2F 的好武器搬到了手机里、还砍掉了密码——听起来像是「终于完美的方案」。但任何安全方案在工程上落地,都会在**你没想到的角落**留下新的麻烦。这一节我们就**诚实地把这些角落翻出来**。

1. 切换门槛:现实是「半新半旧」的乱局

Passkey 已经存在几年了,但**绝大多数网站和服务都还没接入**。今天你打开 100 个常用 App,**可能只有 20 个支持 Passkey**,剩下 80 个还在用「密码 + 短信验证码」。

这意味着两件事同时成立:

更麻烦的是**迁移过渡期**。一个老用户在某个银行既设过密码,也注册了 Passkey,**两条登录路径都还开着**。攻击者骗你输入密码那条老路径——照样能登。Passkey 的抗钓鱼能力**只在用户被引导走 Passkey 流程时才生效**。

2. 恢复盲点:所有设备一起丢怎么办

Passkey 私钥要么存在你手机里,要么跟 iCloud Keychain / Google Password Manager 同步。**这两条路都有"全盘崩盘"的场景**:

**注意,这个风险点不是 Passkey 发明出来的,是它从 U2F「物理钥匙丢失」那里继承下来、又换了个形态**——U2F 时代是「别丢钥匙」,Passkey 时代变成「**别丢云账号 + 别让客服被骗**」。

flowchart TD
    A[你的 Passkey 私钥] --> B[iCloud/Google 同步通道]
    B --> C[云账号本身的安全]
    C --> D[云账号密码强度]
    C --> E[云账号的二次验证]
    C --> F[客服支持流程<br>社工突破口]
    D -->|弱密码/撞库| G[云账号被攻破]
    E -->|被绕过| G
    F -->|被骗重置| G
    G --> H[攻击者拿到<br>所有设备的 Passkey]

这张图就是 Passkey 时代**新的攻击面**——密码学上没破,但信任链的下游被破。

3. 生物识别失败:兜底往往就是最弱的那一环

面容 ID 看起来很酷,但**它会失败**——

**这时候系统会让你输入设备 PIN 码(iPhone 是 6 位数字锁屏密码)兜底**。

**这一下就出事了**——PIN 码通常是 4 到 6 位数字,**强度远低于过去的复杂密码**。攻击者只要拿到你手机 + 猜出/偷看到 PIN 码,**就绕过了一切生物识别和 Passkey 的防线**。

所以你手机本身的锁屏密码强度,**反而成了 Passkey 体系的最终防线**。这是一个**反直觉但真实**的结论:换上 Passkey 之后,**最关键的密码反而变成了你从来没当回事的 6 位锁屏 PIN**。

4. 新形态社工:攻不破密码学,就去骗人

Passkey 抗钓鱼、密码学强度够——攻击者**理性地**会把精力放在「**绕过 Passkey,去攻下游信任链**」上。最常见的三条路:

**路 1:钓鱼你的云账号** 「您的 iCloud 账号在异地登录,验证码已发到您手机……」骗子让你**主动把验证码念出来**,拿下 iCloud,进而拿下你所有 Apple 设备的 Passkey。

**路 2:骗客服重置你的账号** 打电话给 Apple/Google 客服,**冒充你本人**(用泄露的身份证号、出生日期等个人信息),骗客服重置你的云账号。**真实案例**已经多次发生——苹果在 2018 年被媒体曝光的「青少年账号被社会工程攻破」事件就是这类。

**路 3:骗你亲手注册一个攻击者控制的 Passkey** 钓鱼站说「为了你的账户安全,请重新注册 Passkey」,**你亲手把一个新 Passkey 注册到了攻击者的域名下**——或者更狡猾的,钓鱼站直接把你重定向到**真域名下的注册流程**(通过了来源绑定),让你**在不知情的情况下**多注册一个攻击者控制的设备。

注意第三种是**理论上最难完全防住的**——来源绑定机制能防「假域名」,但**骗你在真域名上做错事**,还得靠用户自己警觉。

5. 一句话归纳:Passkey 的安全是「整体工程」

Passkey 抗钓鱼、密码学强度、跨设备同步——这些**组件单独看都极强**。但工程现实是:它们通过**云同步、iCloud/Google 账号、设备 PIN、客服流程、人** 这条长长的信任链连起来。**链条上任一环的薄弱,都会被攻击者精准利用**。

**要点**:Passkey **不是银弹**——切换过渡期让钓鱼者有可乘之机,所有设备丢失或云账号被破会全盘崩盘,6 位设备 PIN 是常被忽略的最终防线,社工攻击者会绕开密码学去攻云账号和客服流程。**Passkey 强的是组件,整体安全仍取决于你把整条链都做对**。

总收束:Passkey 把哪几件事同时做成了

总收束:Passkey 把哪几件事同时做成了

前 5 节我们一路拆解了 Passkey 的对手、它自己的工程实现、还有它留下的新风险。**这一节我们跳出来,把它放在「无密码登录方案」这个大坐标系里看一眼——它究竟同时做对了什么,又仍要依靠什么。**

1. 一件「看似不可能」的事

做登录方案的设计师其实**长期面对一个不可能四角**:

**过去这四个目标,任意挑两个都不难,四个同时做到几乎没有方案做到**。我们快速回看一遍本模块走过的对手:

**Passkey 是第一个把这四个目标同时做到接近最优的方案**——这就是它的独到之处。

2. 四个目标各自做到了什么程度

**无密码**:**彻底**——你不再记、输、管理任何密码。账号的「钥匙」是手机/电脑里自动生成和存储的公私钥对。

**抗钓鱼**:**从密码学层面强制**——私钥被绑死在**注册时认定的那个域名**上。钓鱼站发来的登录请求里带着假域名,**私钥在协议层就拒绝解锁**。这一关是**比任何其他方案都更硬的护城河**。

**跨设备可用**:**靠两层**——**近场**用蓝牙(让另一台设备的 Passkey 借这部手机用一下);**远场**用云同步(私钥在 iCloud/Google Password Manager 里多设备同步)。比 U2F 那种「必须带硬件钥匙」灵活了一个数量级。

**易用**:**接近密码的体验**——面容/指纹一刷就登录,**比输密码还快**。这是它**能真正普及**的关键——过去的安全方案大多输在「用户嫌麻烦所以不用」上。

flowchart TD
    A[Passkey 同时做成的四件事]
    A --> B[无密码<br>私钥替你扛]
    A --> C[抗钓鱼<br>私钥锁死域名]
    A --> D[跨设备可用<br>蓝牙+云同步]
    A --> E[易用<br>面容指纹一键]
    B -.仍需依赖.-> F[iCloud/Google 同步通道]
    C -.仍需依赖.-> G[你当前设备未被入侵]
    D -.仍需依赖.-> H[手机在身边 或 云同步开]
    E -.仍需依赖.-> I[设备 PIN 强度够]
    A -.还有.-> J[客服流程可信]
    A -.还有.-> K[域名管理没被劫持]

3. 它仍要依靠什么

四个目标做到了,**代价是把信任延伸到了新的一串链条上**。Passkey 仍要依靠:

**这意味着**:Passkey 不是一个「装上就万事大忧」的开关,**它把「密码学之外的安全责任」重新分配**给了云厂商、设备制造商、客服流程设计者、域名管理者——**以及你自己**。

4. 为什么要向别人讲清这件事

你是市场运营背景,未来大概率要跟同事、用户、甚至老板解释「为什么我们要支持 Passkey」——别只说「它更安全」。**真正有说服力的说法是**:

> 「Passkey 是目前**唯一**同时把『无密码、抗钓鱼、跨设备、好用』四件事都做对的主流方案。**它不是没有缺点**——它把风险推到了云账号、设备 PIN、客服流程上——**但这些下游风险,整体仍然比『弱密码+短信验证码』的传统组合小一个数量级**。」

**要点**:Passkey 的独到不是「比谁多做了什么」,而是**第一次同时把无密码、抗钓鱼、跨设备、易用四件事做齐**。它的代价是把信任链延伸到了云同步、设备 PIN、客服流程上——**仍是工程问题,但已比过去的方案整体更接近最优**。

学习笔记

无密码方案横向对比

一、短信与邮件验证码的软肋

短信验证码被设计成「只有你能收到」,但实际传输路径上每一站都不对它负责。

1. SIM 卡劫持

攻击者冒充用户联系运营商客服,将号码转移到自己控制的 SIM 卡上。转移后用户手机失联,攻击者接收所有短信验证码与运营商通知。真实案例:2019 年 Twitter CEO Jack Dorsey 账号被攻破;2022 年 Uber 攻击事件中先劫持 SIM 再钓鱼内部员工。

2. 电信层漏洞

共同点:用户完全无感知,验证码在眼皮底下被复制。

3. 邮件账号被破

邮件恢复机制本身是链式(忘记密码 → 短信验证 → 找回)。当短信被攻破,或邮箱密码弱且多处复用时,攻击者可接收所有重置密码邮件、安全提醒,并接管所有以邮箱为备用登录的账号。结论:「邮箱一破,百站沦陷」。

架设实时中转站(非静态假页)

架设实时中转站(非静态假页),同时绕过密码和第二因素。流程:受害者输入账号密码 → 代理站实时转发给真网站 → 真网站发短信验证码给受害者 → 代理站显示验证码输入框收集后再转发给真站 → 完成登录、劫持会话。受害者全程以为操作正确。

二、魔法链接的边界

魔法链接指输入邮箱、点收件箱链接直接登录(如 Notion、Slack)。体验上用户不用记、不用装、链接一次性,但**这三件「安全」全是表面上的**。

魔法链接没消灭钥匙

魔法链接没消灭钥匙,只是把钥匙从「脑子里的密码」换成「收件箱里的链接」。链式信任:魔法链接强度 = 邮箱强度。邮箱本身的登录方式(弱密码、短信验证码、App 扫码)任一被破 → 所有用魔法链接登录的账号全部沦陷。前序模块讲过大多数人邮箱密码是早年设的弱密码且多处复用。

AitM 同样可中转魔法链接

AitM 同样可中转魔法链接。攻击者可实时从邮件中抠出真链接转发完成登录、抢走会话;或事先已登录邮箱,看到魔法链接立刻在另一台设备点;更狡猾的变种是直接篡改邮件内容。关键差异:攻击魔法链接只需破邮箱,方法比破 SIM 卡多且便宜。

边界三:邮件服务商自身也会出问题

即使邮箱密码超强、开了双因素,邮件服务商后台被攻破的案例也发生过,用户在这一层完全无能为力。

三、推送确认与社交登录的局限

推送确认的「服务器信任」陷阱

流程:输入用户名密码 → 手机弹推送「是否允许登录」→ 点允许即完成。关键问题:你点的「允许」是针对服务器发来的推送消息,而非验证登录行为本身。服务器发推送是因为收到了一次密码正确的请求,但「正确」可能来自攻击者(撞库、弱密码、数据泄露)。只要攻击者知道密码,就能反复触发推送。

攻击者拿到用户名密码后用脚本反复触发登录

攻击者拿到用户名密码后用脚本反复触发登录,手机疯狂震动,用户从拒绝到疲劳到条件反射点允许,或误以为系统消息点确认。真实案例:2022 年 Uber 数据泄露,起因是外包员工被轰炸后,被冒充 IT 部门的人在 WhatsApp 上骗去点允许并交出后续验证信息。整条攻击链没破一道密码学,破的是人的耐心和信任。

判断「这次登录是否合法」的不是你的设备,是服务器

判断「这次登录是否合法」的不是你的设备,是服务器。后果:服务器被攻破可伪造推送;钓鱼代理可实时转发「允许」;推送里的设备、位置信息完全由服务器生成,服务器说啥你只能信啥。

四、FIDO U2F 与 Passkey 的异同

U2F 的定位

全称 Universal 2nd Factor(通用第二因素),关键词是「第二」——仍是密码 + 物理设备(YubiKey)双因素。

U2F 的核心贡献:抗钓鱼的来源绑定

注册时 U2F 设备为该网站生成密钥对,且**被锁定在具体域名**。登录时设备用私钥对挑战做签名,硬约束:只会在请求来自注册时的那个域名时才执行。结果:钓鱼站收到密码、转发验证码、中转链接、伪造推送都能成功,但 U2F 设备看到域名不对就拒绝签名——用户即使主动插上设备并按了也不响应。Google 2017 年强制全员部署硬件密钥后,公开安全简报里提到公司内部再未发生过针对员工的成功钓鱼事件。

U2F 的三个未解决问题
  1. 仍需要密码——第一因素的所有老毛病(弱密码、撞库、复用)一个不少。
  2. 物理设备要随身带——YubiKey 易丢,丢了登不上;需提前注册多把备用并分散在多个物理位置。
  3. 共享设备用不了——公共电脑可能没 USB 口、没驱动、浏览器不支持 U2F;更何况不该把个人硬件插到不控制的电脑上。

企业强制场景行得通,消费级场景几乎推不开。

Passkey 的进化

Passkey 骨子里是 FIDO2 协议(FIDO2 = WebAuthn + CTAP2),核心思想、密码学、来源绑定机制全部继承自 U2F。Passkey 把 U2F 的好武器搬进手机、砍掉密码。

五、Passkey 的残留风险

绝大多数网站还没接入 Passkey

绝大多数网站还没接入 Passkey。今天 100 个常用 App 可能只有 20 个支持,剩下 80 个仍用「密码 + 短信验证码」。后果:用户脑子里必须同时记两套登录方式;还在用旧方式的网站钓鱼风险一点没降。

老用户在某银行既设过密码也注册了 Passkey

老用户在某银行既设过密码也注册了 Passkey,两条登录路径都还开着。攻击者骗走密码那条老路径照样能登——Passkey 的抗钓鱼能力只在用户被引导走 Passkey 那条路径时才生效。