证书是「持有」,密码是「知识」,两类叠起来才叫双因素。 Demo 里四种组合只有一种能进,两种失败还落在不同层。
上一节只有一把锁,这一节加第二把。 要注意的是——两把锁必须是不同性质的,否则只是同一把锁拧两次。
一、四种组合,只有一种能进
Demo 里两层检查:TLS 层要客户端证书,应用层要账号密码。四种组合的结果: | 客户端证书 | 账号密码 | 结果 | |:---:|:---:|---| | 无 | 无 | 握手就断 | | 无 | 有 | 握手就断 | | 有 | 无 | TLS 过了,应用层 401 | | 有 | 有 | 通过,收到 135 字节 | 前两行一样:没有证书,密码再对也没用——因为根本没机会发出去。 第三行是这次实测最有意思的一行:TLS 谈成了,客户端以为自己连上了,结果被应用层挡在 401。 这说明两层是串联的,不是并联。任何一层不过,整个流程就停。
二、为什么必须是两类
证书属于「持有」:你得有那个私钥文件。密码属于「知识」:你得记住那串字符。 两类同时被攻破的概率远小于单独一类:偷了电脑的人未必知道密码;猜到密码的人未必拿得到私钥文件。 这就是双因素的全部逻辑。 反例:密码加「密保问题」,两个都是知识,攻破一个的思路往往能攻破另一个,所以不算双因素。 密码加短信验证码才算——手机是「持有」。 再往上一层是「无密码」:只靠持有(比如 passkey,私钥存在设备的安全芯片里,用生物特征解锁)。 它本质上还是双因素——持有设备加特征解锁,只是把「知识」那一项去掉了。
三、代价换来了什么
代价是复杂度:用户要装证书、选证书、证书过期要换。所以这套组合基本只出现在内部系统和高价值后台。 换来的是抗钓鱼。 密码可以被骗走,验证码可以被转发,但客户端证书的私钥不会离开设备——钓鱼网站拿不到它, 因为它只在跟真服务端握手时才会用到。 这一点在今天的攻防里越来越重要:验证码中间人攻击(把验证码实时转发给真站点)已经做得很成熟, 而客户端证书对这类攻击天然免疫。
四、动手 Demo:四种组合,两条不同的失败路径
同一个服务端,TLS 层要求客户端证书,应用层要求 Basic 凭据。 客户端按「有没有证书」「有没有密码」四种组合各试一次,看失败发生在哪一层。
# TLS 层:要证书
sctx.verify_mode = ssl.CERT_REQUIRED
sctx.load_verify_locations(ca_p)
# 应用层:要密码
cred = base64.b64encode(b'bozai:pa55word').decode('ascii')
extra = [(u'Authorization', u'Basic ' + cred)]
实跑输出:
--------------------------------------------------------------------
双因素:证书 + 密码,缺一个都不行
--------------------------------------------------------------------
两层检查:TLS 层要客户端证书,应用层要账号密码。
四种组合各试一次:
证书=无 密码=无 失败:ConnectionResetError
证书=无 密码=有 TLS 就断了:TLSV13_ALERT_CERTIFICATE_REQUIRED
证书=有 密码=无 TLS 过了,但应用层要密码 → 401
证书=有 密码=有 通过,收到 135 字节
四种组合里只有最后一种能进。前两种失败的位置不同:
没证书 → 卡在 TLS 握手,连 HTTP 都没开始;
有证书没密码 → TLS 过了,卡在 401。
这就是「双因素」的含义:两类**不同性质**的证据。
证书属于「持有」——你得有那个文件;
密码属于「知识」——你得记住那串字符。
两类同时被攻破的概率远小于单独一类:偷了电脑的人未必知道密码,
猜到密码的人未必拿得到私钥文件。
证书=无 密码=无:ConnectionResetError,握手就断。
证书=无 密码=有:同样 ConnectionResetError——密码根本没机会发。
证书=有 密码=无:TLS 通过,应用层回 401。这是唯一能看到 HTTP 状态码的失败。
证书=有 密码=有:通过,收到 135 字节。四行里只有这一行成功。
30 秒实验
- 把第二行的密码换成错的,看结果和「无证书」有没有区别。
- 把
CERT_REQUIRED改成CERT_OPTIONAL,重新跑四种组合。 - 想一想:短信验证码为什么算第二因素,而密保问题不算?
常见误区
- 「密码加密保问题是双因素」——两个都是知识。
- 「两层是并联关系,过一层就行」——是串联,任何一层不过都停。
- 「客户端证书也能被钓鱼」——私钥不离开设备,钓鱼拿不到。
自测三问(点开对答案)
1. 双因素里的「两因素」指什么? —— 两类不同性质的凭据,比如持有(证书)加知识(密码)。 2. 只有证书没有密码时,失败在哪一层? —— 应用层,回 401——TLS 已经通过了。 3. 为什么客户端证书抗钓鱼? —— 私钥不离开设备,只在跟真服务端握手时使用,钓鱼站拿不到。这套方案很强,但很少有网站对公众用它。下一节用数字说明为什么。
- ☐ (本节完,下一节 8.4.3 SSL客户端认证必要的费用)