安全协议设计与分析(3)

本节的主要内容身份认证与安全协议

为从"为什么要认证"开始,到"怎么认证",再到"认证协议怎么设计才安全",最后讨论密钥协商和秘密共享


一、认证是干什么的

在网络上,你和一个服务器通信时,双方都需要确认对方的身份------你说你是Alice,我怎么知道你不是Trudy?反过来,Alice也要确认自己连接的是真的Bob服务器,而不是一个钓鱼站点。这个过程就叫认证(Authentication)

认证的核心问题说白了就一句话:一个实体向另一个实体证明自己的某种声称属性是真实的。这里的"实体"可以是人、主机、进程,甚至是一个俱乐部成员资格。

实际中认证通常包含三个层面的含义:

  • 身份认证:验证"你是谁",确认通信方的身份是否属实。
  • 数据源认证:验证消息确实来自声称的发送者,且中途没有被篡改,同时还要确保消息不是旧的(即"新鲜性")。
  • 密钥建立认证:在完成身份认证的同时,协商出一个会话密钥供后续加密通信使用。

后面我们会看到,一个好的认证协议往往要把这三件事一起解决。


二、口令认证:最古老也最头疼的方法

2.1 口令是怎么认证身份的

认证有三种基本途径,也就是常说的三要素:

  • 你知道什么(口令、PIN码)
  • 你拥有什么(智能卡、USB Key)
  • 你是谁(指纹、虹膜等生物特征)

口令属于第一类,也是目前最普遍的方式。它的基本原理极其简单:用户注册时把口令交给服务器存着,登录时再输入口令,服务器比对。如果一致,就认定是你。

这个模型的问题是显而易见的。

2.2 最直白的攻击方式

网络嗅探。如果口令在网络上明文传输,同一网段的任何人都能看到。早期的很多协议就是这个毛病------把口令直接写在消息里发过去。

重放攻击。就算你把口令哈希之后再传,攻击者虽然不知道原文是什么,但他可以直接把你发的哈希值截获下来,然后原样"重放"给服务器,服务器照样认为是你。因为哈希值每次都是一样的,没有"新鲜度"的概念。

钓鱼 。攻击者搭一个假网站,长得跟真的一样,把用户的口令骗过来。用户面对网页时其实很难准确判断这个网站到底是真是假。更隐蔽的是通用密码问题------你为了方便记忆,在很多网站上用同一个口令,结果一个低安全性网站的数据库被拖了,你在高安全性网站的账户也跟着完蛋。

2.3 一个朴素的防御思路:口令哈希

既然不能把同一个密码原样交给每个网站,那就给每个网站生成一个唯一的版本:

复制代码
hash(password + "banka.com")  →  Q7a+0ekEXb
hash(password + "siteb.com")  →  OzX2+ICiqc

这样,即便某个网站的哈希值泄露了,攻击者拿着一长串哈希也无济于事------换一个网站就完全是另一个值了。这是客户端的一种安全防范策略,事实上现在很多密码管理器就在做类似的事情。

2.4 什么样的口令更安全

直觉上,"123456"显然不安全,"jfIej(43j-EmmL+y"显然更安全。问题在于,人类记忆能力有限,几十上百个账户的情况下,用户要么选简单的、有规律的口令,要么就在不同账户之间重用一个口令。

现实中常见的口令设置策略包括:长度限制、必须包含数字、必须包含大小写、必须包含特殊字符、以及黑名单机制。NIST(美国国家标准与技术研究院)发布的数字认证指南就是用来指导这些策略的,但早期的指南缺乏用户行为的实证数据支撑。


三、口令强度到底怎么评估

3.1 两步分析框架

评估一个口令数据集的安全性,通常分两步:先做特征分析 ,再做可猜测性分析

特征分析关注的是"人们倾向于怎么设置口令":

  • 字符分布:数字、字母、特殊字符各占多少比例。
  • 结构模式 :如果记L为字母段、D为数字段、S为特殊字符段,那么 password123 的结构就是 L₈D₃,abc!123 就是 L₃S₁D₃。统计这些结构的流行程度能够揭示人们设置口令的习惯。
  • 键盘模式 :很多人会直接在键盘上划------同行的连续字符(如 asdfgh)、锯齿形(如 qawsxd)、蛇形(如 zxcfgh)。
  • 语义模式:中文拼音、英文单词、生日日期(6位或8位)在哪几个位置出现,这些都是攻击者重点尝试的方向。

通过分析泄露的明文口令库(仅国内就有数亿条明文记录泄露过),可以清晰地看出最流行的口令和最常见的行为模式。

3.2 熵:衡量不确定性的数学工具

口令强度的本质,是攻击者猜出它的难易程度。Shannon在1948年提出信息熵的概念,用来度量一个随机变量的不确定性。

如果一个信源有n种取值 U₁, U₂, ..., Uₙ,对应概率为 p₁, p₂, ..., pₙ,那么Shannon信息熵为:

H(X)=−∑i=1npilog⁡2pi H(X) = -\sum_{i=1}^{n} p_i \log_2 p_i H(X)=−i=1∑npilog2pi

但Shannon熵描述的是"平均"不确定性,对口令场景来说有些不够用。因为攻击者根本不会按均匀分布去猜------他们总是先猜 123456,再猜 password。所以实际中用得更多的是下面几个指标:

  • 最小熵 (Min Entropy):只关注概率最大的那个事件,衡量"最坏情况"下的不确定性。

    H∞(X)=−log⁡2(p1) H_{\infty}(X) = -\log_2(p_1) H∞(X)=−log2(p1)

    这里 p₁ 是概率最大的那个口令出现的概率。如果数据集中 123456 占了30%,那么最小熵就由它决定。

  • 猜测熵 (Guessing Entropy):假设攻击者按概率从高到低依次猜测,猜到任意一个口令平均需要尝试多少次。

    G(X)=∑i=1Npi⋅i G(X) = \sum_{i=1}^{N} p_i \cdot i G(X)=i=1∑Npi⋅i

    其中 pᵢ 是按降序排列后的第i个概率。

  • β-success-rate(β成功率):攻击者被限制最多进行β次尝试时,他的平均成功率。

    λβ(X)=∑i=1βpi \lambda_{\beta}(X) = \sum_{i=1}^{\beta} p_i λβ(X)=i=1∑βpi

  • α-work-factor(α工作量因子):攻击者想要达到至少α的成功率,每个账户至少需要尝试多少次。

    μα(X)=min⁡{j  |  ∑i=1jpi≥α} \mu_{\alpha}(X) = \min\left\{j \;\middle|\; \sum_{i=1}^{j} p_i \geq \alpha\right\} μα(X)=min{j i=1∑jpi≥α}

举个例子,假设一个数据集里 123456 占30%,iloveyou 占20%,123456789 占10%。那么:

  • α = 0.4 时,α-work-factor = 1(只需猜 123456 就能覆盖40%的账户)
  • α = 0.9 时,α-work-factor = 3(猜前三个就能覆盖90%)

这就是为什么一个看似"需要尝试上亿次"的口令空间,在实际中很可能几千次尝试就能拿下相当比例的账户。

3.3 攻击者是怎么批量猜口令的

这里说的攻击叫漫步口令猜测攻击(Trawling Guessing)------攻击者不关心具体攻击谁,只是在允许的猜测次数内尽量多猜出一些账户。

基于PCFG(概率上下文无关文法)的方法,是2009年Weir等人提出的第一个全自动化猜测算法。核心思路是:

  1. 训练阶段:对泄露口令进行解析,统计每种结构(如 L₄D₃、L₅S₁D₂)出现的频率(结构频率表 Σ₁),以及每种结构中字母段/数字段/特殊字符段的具体内容频率(字段频率表 Σ₂)。
  2. 猜测集生成阶段:按 Σ₁ 和 Σ₂ 中统计的概率降序生成猜测集。

一个口令 wang123! 会被解析为 L₄(wang)、D₃(123)和 S₁(!),那么它的概率为:

P(wang123!)=P(L4D3S1)×P(L4→wang)×P(D3→123)×P(S1→!) P(\text{wang123!}) = P(L_4D_3S_1) \times P(L_4 \to \text{wang}) \times P(D_3 \to 123) \times P(S_1 \to !) P(wang123!)=P(L4D3S1)×P(L4→wang)×P(D3→123)×P(S1→!)

整个思路本质上是:先确定"结构"有多常见,再确定在那种结构下的"内容"有多常见。

基于Markov模型的方法 (Narayanan & Shmatikov, 2005)则换了一个思路:它假设用户构造口令时是从左往右一个字符接一个字符地输入。在4阶Markov模型下,口令 abc123 的概率是:

Pr(abc123)=Pr(a∣⊢)⋅Pr(b∣a)⋅Pr(c∣ab)⋅Pr(1∣abc)⋅Pr(2∣abc1)⋅Pr(3∣bc12) Pr(\text{abc123}) = Pr(a|\vdash) \cdot Pr(b|a) \cdot Pr(c|ab) \cdot Pr(1|abc) \cdot Pr(2|abc1) \cdot Pr(3|bc12) Pr(abc123)=Pr(a∣⊢)⋅Pr(b∣a)⋅Pr(c∣ab)⋅Pr(1∣abc)⋅Pr(2∣abc1)⋅Pr(3∣bc12)

其中 ⊢ 表示起始符号。训练阶段统计每个子串后面跟每个字符的频数,猜测时按条件概率从高到低生成。

PCFG着眼于结构层面,Markov着眼于字符转移层面,两者的共同点是都从真实泄露数据中学习人类的口令构造习惯。

3.4 口令世界的困境

口令面临一个根本矛盾:可记忆性 vs. 抗猜测性------前者希望口令短、有规律、简单;后者希望口令长、无规律、复杂。这两者是直接对立的,不存在一个完美的折中方案。

目前学界的共识是:

  • 保核心:重要账户用强口令,不重要的可以随便一些
  • 减负担:同级别账户用类似口令
  • 不越级:不同级别账户绝对不重用类似口令
  • 如果使用口令管理软件,最好是自己编写的(信任问题)

四、认证协议:从"最低配"到"安全"

前面讨论的是"用什么信息来认证",接下来要关注的是"在网络上怎么交互才能安全地完成认证"------这就是认证协议设计的核心问题。

这里先说明一下符号约定。后面会反复出现这些记号:

  • {M}_Alice:用Alice的公钥加密消息M
  • [M]_Alice:用Alice的私钥对M签名
  • E(M, K):用对称密钥K加密M
  • h(...):哈希函数
  • Alice和Bob分别代表通信双方,Trudy代表攻击者

4.1 最原始的做法:直接传口令

复制代码
Alice → Bob: "I'm Alice"
Bob → Alice: Prove it
Alice → Bob: My password is "frank"

这个协议有两个致命缺陷:Trudy截获口令后可以直接拿去用(明文传输),而且就算Trudy当时没截获完整口令,她只要把之前偷听到的消息原样重放给Bob,Bob照样会认为她就是Alice。

改进一:做个哈希。

复制代码
Alice → Bob: "I'm Alice"
Bob → Alice: Prove it
Alice → Bob: h(Alice's password)

这样至少口令本身不会直接暴露。但Trudy依然可以截获 h(password) 然后重放------哈希值每次都是一样的,没有任何"这次"的特征。

4.2 核心机制:挑战-应答(Challenge-Response)

解决问题的关键思想是:每次认证时,服务器先发一个一次性随机数(Nonce),客户端把这个随机数和自己知道的口令或密钥混合在一起做运算,结果返回服务器。服务器也做同样的运算,对比结果。

复制代码
Alice → Bob: "I'm Alice"
Bob → Alice: Nonce
Alice → Bob: h(Alice's password, Nonce)

解释一下为什么这样就防住了重放:

  • Nonce是Bob每次新生成的,用过一次就作废。
  • 即便Trudy截获了 h(password, old_nonce),下次Bob发一个新的Nonce,这个旧响应就完全没用了。
  • Nonce保证了"新鲜性"------每次的挑战值不同,每次的应答也不同。

Nonce可以用随机数,也可以用时间戳。时间戳的好处是省掉一轮消息交换,但代价是双方时钟需要大致同步,而且时间本身成了一个关键安全参数。

4.3 对称密钥认证

把口令换成共享的对称密钥 K,对Nonce做加密而不是哈希:

复制代码
Alice → Bob: "I'm Alice"
Bob → Alice: R
Alice → Bob: E(R, K)

Bob用同样的密钥K解密,比对R是否正确。能正确解密,就说明对方确实持有K------因为只有Alice和Bob知道这个密钥。

但注意,这个协议只做到了单向认证:Bob认证了Alice,但Alice并没有认证Bob。Trudy完全可以假装成Bob给Alice发Nonce。

4.4 双向认证(相互认证)及其陷阱

很自然地想到:把上面的过程反过来再做一次就行了。于是有了第一个双向认证的尝试:

复制代码
Alice → Bob: "I'm Alice", R_A
Bob → Alice: R_B, E(R_A, K)
Alice → Bob: E(R_B, K)

这个协议看起来对等、工整,但实际上存在一个很典型的漏洞------反射攻击(Reflection Attack)

Trudy可以在Bob面前伪装成Alice:

  1. Trudy 以"Alice"的身份发 R_A 给Bob
  2. Bob 返回 R_B 和 E(R_A, K)
  3. Trudy 开启一个新的连接,又以"Alice"的身份发 R_B 给Bob
  4. Bob 返回 R_C 和 E(R_B, K)
  5. Trudy 拿着第4步得到的 E(R_B, K) 回到第1个连接中,发给Bob

Bob收到 E(R_B, K) 后验证通过,就以为Trudy是Alice。

这个攻击揭示了一个深刻的经验法则:不要在双向认证中让双方做完全对称的操作。对称意味着攻击者可以利用一方来欺骗另一方。

修正方案很简单------在加密内容中加入身份标识:

复制代码
Alice → Bob: "I'm Alice", R_A
Bob → Alice: R_B, E("Bob", R_A, K)
Alice → Bob: E("Alice", R_B, K)

只是多加了身份标签,但彻底堵住了反射攻击的路。安全协议设计就是这样,往往一个微小的改动就能产生质的变化。

4.5 公钥认证

利用非对称密码体制,思路类似,但换成公私钥对:

基于公钥加密的认证(首次尝试):

复制代码
Alice → Bob: "I'm Alice"
Bob → Alice: {R}_Alice
Alice → Bob: R

Bob用Alice的公钥加密R,只有持有私钥的Alice能解密出R。但如果加密和签名用的同一个密钥对,Trudy可以让Alice"帮"自己解密任何东西------这本质上相当于把Alice当成解密预言机。所以加密和签名必须用不同的密钥对

基于数字签名的认证

复制代码
Alice → Bob: "I'm Alice"
Bob → Alice: R
Alice → Bob: [R]_Alice

Alice对R签名,Bob用Alice的公钥验证。同样地,签名密钥对和加密密钥对要分开,否则Trudy可以诱骗Alice对任何东西签名。

4.6 认证的同时建立会话密钥

认证完成后,双方通常还需要一个会话密钥(Session Key),用于后续通信的加密和完整性保护。这个密钥只存在于当前会话中------即便攻击者以后拿到了长期密钥,也没法解密本次会话的记录。这就是**完全正向保密(Perfect Forward Secrecy, PFS)**的思想。

把认证和会话密钥结合在一起的尝试:

对称密钥版本(有问题):

复制代码
Alice → Bob: "I'm Alice", R
Bob → Alice: {R, K}_Alice
Alice → Bob: {R+1, K}_Bob

这里Bob生成了会话密钥K,但Alice没法认证Bob------Alice的Nonce值R在这里根本起不到认证Bob的作用。

签名版本(有严重漏洞):

复制代码
Alice → Bob: "I'm Alice", R
Bob → Alice: [R, K]_Bob
Alice → Bob: [R+1, K]_Alice

问题出在哪?签名是公开可验证的!任何人拿到Bob的签名消息 [R, K]_Bob,用Bob的公钥就能解开看到K。密钥直接在签名里暴露了。

先签名后加密(仍然不安全------中间人攻击):

复制代码
Alice → Bob: "I'm Alice", R
Bob → Alice: { [R, K]_Bob }_Alice
Alice → Bob: { [R+1, K]_Alice }_Bob

Trudy的攻击路径:

  1. Trudy截获第1条消息,将R转给Bob,但声称自己是"Trudy"
  2. Bob用Trudy的公钥加密 [R, K]_Bob 返回
  3. Trudy用自己的私钥解密(注意外层是用Trudy公钥加密的),拿到Bob的签名 [R, K]_Bob,从而获得K
  4. Trudy把 [R, K]_Bob 用Alice的公钥加密返回给Alice
  5. Alice以为在和Bob通信,拿到的却是Trudy转发的密钥K

先加密后签名(这版是对的):

复制代码
Alice → Bob: "I'm Alice", R
Bob → Alice: [ {R, K}_Alice ]_Bob
Alice → Bob: [ {R+1, K}_Bob ]_Alice

先加密保证了只有接收方能看到密钥,再签名保证了发送方的身份。这个顺序是关键的:签在外层,别人没法剥离签名偷换内容。

4.7 完全正向保密(PFS)

前面的方案都有一个隐含的假设:如果长期密钥K日后泄露了,之前记录的加密通信就全都能被解密。PFS要解决的就是这个问题------即使长期密钥泄露,过去的会话也不能被解密。

PFS的关键是使用临时密钥(Ephemeral Key)。最经典的实现是对称密钥保护下的临时Diffie-Hellman:

复制代码
Alice → Bob: E(g^a mod p, K)
Bob → Alice: E(g^b mod p, K)

双方在长期密钥K的保护下交换临时的DH公开值 g^a 和 g^b,会话密钥 K_S = g^{ab} mod p。会话结束后,双方各自丢弃临时指数a和b。此后即使K泄露,攻击者也无法从截获的密文中恢复出 g^{ab}------而DH问题本身的困难性(离散对数)保证了这一点。

这种方案叫做短时Diffie-Hellman(Ephemeral DH),在TLS等实际协议中广泛使用。DH本身容易遭受中间人攻击(因为传输 g^a 时没人知道是Alice还是Trudy发的),但这里用长期密钥K加密传输,相当于在DH外面包了一层认证,同时解决了MiM和PFS两个问题。

4.8 用时间戳替代Nonce

有时候为了减少消息轮数,会用时间戳T替代Nonce。在公钥体系下:

复制代码
Alice → Bob: "I'm Alice", { [T, K]_Alice }_Bob
Bob → Alice: { [T+1, K]_Bob }_Alice

时间戳的好处是少了一轮交换,但代价是双方时钟必须大致同步(需要容忍一定的时间偏斜),而且时间成了关键安全参数------Trudy如果能在时间窗口内发起攻击,就仍然有机会。


五、Diffie-Hellman密钥协商

5.1 基本思想

前面的协议里,会话密钥要么由某一方生成后传输给另一方,要么由KDC分发。但在某些场景下,我们希望密钥由通信双方共同生成------在协议完成之前,谁也不知道最终密钥长什么样。

Diffie-Hellman协议(1976年)就是为此设计的,也是应用最广泛的密钥协商协议。它允许双方通过公开信道交换一些公开值,然后各自独立计算出相同的共享密钥。

5.2 协议过程

选定一个有限群G(通常是模大素数p的乘法群),以及一个生成元g。

复制代码
Alice: 选取随机数 a, 计算 g^a mod p, 发送给Bob
Bob:   选取随机数 b, 计算 g^b mod p, 发送给Alice

Alice: K = (g^b)^a = g^{ab} mod p
Bob:   K = (g^a)^b = g^{ab} mod p

实例(p = 23, g = 7):

步骤 Alice (a=3) Bob (b=6)
计算并发送 7³ mod 23 = 21 7⁶ mod 23 = 4
收到对方值后计算 4³ mod 23 = 18 21⁶ mod 23 = 18

双方都得到 K = 18。

5.3 安全性基础

DH的安全性建立在离散对数问题的困难性上:从 g^a mod p 推导出 a 在计算上是不可行的。攻击者虽然能看到 g^a 和 g^b,但无法高效计算出 g^{ab}。

需要注意的是,裸的DH协议不提供认证------攻击者可以在中间分别和Alice、Bob各自建立一个DH连接(中间人攻击)。所以实际使用中DH总是需要搭配某种认证机制(如数字签名)一起用。


六、口令之外:其他认证方式

6.1 动态口令(基于信任物体)

口令的问题在于它是静态的------一旦被截获就能反复使用。动态口令每次都不一样,即使被截获下次也用不了。

对称密钥方式

复制代码
Alice → Bob: "I'm Alice"
Bob → Alice: R(随机挑战值)
Alice: 输入PIN激活令牌 → 令牌计算 h(K, R) → 发给Bob
Bob: 同样计算 h(K, R) → 比对

令牌每分钟或每次操作产生一个不同的口令。服务器也做同样的计算。挑战值R可以是服务器下发的随机数,也可以是时间戳。

非对称密钥方式:秘密值是示证者的私钥,验证者持有公钥。挑战值用公钥加密后由示证者解密返回------能正确解密就等于证明了持有私钥。

6.2 生物特征认证

生物特征是"你是谁"这一因素。常用的包括指纹、虹膜、人脸、声音等。选用生物特征需要满足四个条件:普遍性(人人都有)、唯一性(人人不同)、可测量性、稳定性(不随时间急剧变化)。

指纹识别:采集图像 → 增强处理 → 提取特征点 → 与数据库比对。本质上是统计匹配,不是精确相等。

虹膜扫描 :虹膜的随机发育过程使其具有极高的唯一性,且遗传影响小、终身稳定。扫描后通过二维小波变换生成256字节(2048位)的虹膜码,然后计算两个虹膜码之间的汉明距离

d(x,y)=不匹配的位数比较的总位数 d(x, y) = \frac{\text{不匹配的位数}}{\text{比较的总位数}} d(x,y)=比较的总位数不匹配的位数

实操中的阈值:相同虹膜的汉明距离约0.08,不同虹膜约0.50。通常设定阈值为0.32------小于这个值就认为匹配。

6.3 错误率权衡

生物特征系统有两种错误:

  • 错误接受率(FAR):把冒充者错误地认证为合法用户
  • 错误拒绝率(FRR):把合法用户错误地拒绝

这两个是跷跷板------降低一个必然抬高另一个。**等错误率(EER)**是两者相等时的错误率,用来横向比较不同技术的性能。在理论上,虹膜扫描可以达到 10^{-5} 级别的等错误率,但需要极其精准的注册过程。

6.4 多因子认证:1+1>2

双因素认证意味着同时使用两个不同维度的认证因素------比如 ATM卡(你有什么)+ PIN码(你知道什么)。关键要求是:这两个因素之间不能互相推导

这里有一个看似"双因素"实则挂羊头卖狗肉的例子:动态口令卡需要一个开机密码来激活,看起来"卡"和"密码"是两个因素。但如果这个开机密码是存在卡里的,那么拿到卡的人物理上就能提取出密码------两个因素退化成了一个。

另一个反例:提供照片+口令的方案,照片识别要么依赖集中数据库(难以支持大用户量),要么数据库分散(不安全)。

6.5 各方对比

比较维度:低成本 | 可用性 | 可再生性

方案 成本 可用性 可再生性
口令
硬件令牌
生物特征

在可预见的未来,口令认证仍将是最主要的认证方式。不是因为口令最安全,而是因为它成本最低、最容易部署、也最为用户所熟悉。其他方案综合来看都有各自的短板,无法全面替代口令。


七、秘密共享:当秘密不能只交给一个人

7.1 现实需求

设想这些场景:导弹发射需要两人同时转动钥匙;核按钮需要多人共同授权;银行保险库需要若干负责人同时到场才能开启。这些场景的共同需求是:秘密不能由一个人独占,必须分散到多个参与者手中,并且只有当足够数量的参与者同时到场时才能恢复。

这就是秘密分割(Secret Sharing)要解决的核心问题。它的形式化描述叫做(t, n)门限方案

  • 将秘密s分割成n个子秘密(shadow/share)
  • 任意t个(及以上)子秘密可以恢复s
  • 任意少于t个子秘密得不到s的任何信息

极端情况下,(n, n)门限方案要求所有人都到场,(1, n)则退化为简单的备份。

7.2 Shamir门限方案的核心思想

Shamir在1979年提出的方案是理解整个秘密共享领域的钥匙。它的思路出人意料地简单:用多项式来隐藏秘密

对于一个(t, n)门限方案:

  1. 构造一个 t-1 次多项式:

    f(x)=a0+a1x+a2x2+⋯+at−1xt−1 f(x) = a_0 + a_1 x + a_2 x^2 + \cdots + a_{t-1} x^{t-1} f(x)=a0+a1x+a2x2+⋯+at−1xt−1

    其中 a0=sa_0 = sa0=s(要保护的秘密),其余系数 a1,...,at−1a_1, \dots, a_{t-1}a1,...,at−1 随机选取。所有运算在有限域 GF§ 上,p为一个大素数。

  2. 任选n个互不相同的 xix_ixi(i = 1, 2, ..., n),计算对应的 yi=f(xi)y_i = f(x_i)yi=f(xi)。每对 (xi,yi)(x_i, y_i)(xi,yi) 就是一个子秘密,分发给一个参与者。

  3. 恢复时,只要有任意t个点,就能唯一确定这个 t-1 次多项式,从而得到 f(0)=a0=sf(0) = a_0 = sf(0)=a0=s。

这里的关键直觉是:平面上两点确定一条直线(t=2),三点确定一条抛物线(t=3),依此类推------t个点唯一确定一个t-1次多项式。 少于t个点,则有无穷多种可能的多项式,秘密被完全隐藏。

7.3 Lagrange插值:数学上怎么恢复

已知t个点 (xi1,yi1),(xi2,yi2),...,(xit,yit)(x_{i_1}, y_{i_1}), (x_{i_2}, y_{i_2}), \dots, (x_{i_t}, y_{i_t})(xi1,yi1),(xi2,yi2),...,(xit,yit),可以用Lagrange插值公式重构多项式:

f(x)=∑j=1tyij∏m=1m≠jtx−ximxij−xim f(x) = \sum_{j=1}^{t} y_{i_j} \prod_{\substack{m=1 \\ m \neq j}}^{t} \frac{x - x_{i_m}}{x_{i_j} - x_{i_m}} f(x)=j=1∑tyijm=1m=j∏txij−ximx−xim

那么密钥 k=f(0)k = f(0)k=f(0):

k=∑j=1tyij∏m=1m≠jt−ximxij−xim k = \sum_{j=1}^{t} y_{i_j} \prod_{\substack{m=1 \\ m \neq j}}^{t} \frac{-x_{i_m}}{x_{i_j} - x_{i_m}} k=j=1∑tyijm=1m=j∏txij−xim−xim

如果令

bj=∏m=1m≠jt−ximxij−xim b_j = \prod_{\substack{m=1 \\ m \neq j}}^{t} \frac{-x_{i_m}}{x_{i_j} - x_{i_m}} bj=m=1m=j∏txij−xim−xim

则有 k=∑j=1tbj⋅yijk = \sum_{j=1}^{t} b_j \cdot y_{i_j}k=∑j=1tbj⋅yij。因为所有的 xix_ixi 是公开的,每个 bjb_jbj 可以预先算好,恢复密钥时只需要做简单的线性组合。

7.4 完整演算示例

构造一个 (3, 5) 门限方案,秘密 k = 11,素数 p = 19。

分割阶段:

随机选 a1=2a_1 = 2a1=2, a2=7a_2 = 7a2=7,常数项 a0=11a_0 = 11a0=11,得到多项式:

f(x)=(7x2+2x+11) mod 19 f(x) = (7x^2 + 2x + 11) \bmod 19 f(x)=(7x2+2x+11)mod19

计算5个子秘密:

  • f(1)=(7+2+11) mod 19=1f(1) = (7 + 2 + 11) \bmod 19 = 1f(1)=(7+2+11)mod19=1
  • f(2)=(28+4+11) mod 19=5f(2) = (28 + 4 + 11) \bmod 19 = 5f(2)=(28+4+11)mod19=5
  • f(3)=(63+6+11) mod 19=4f(3) = (63 + 6 + 11) \bmod 19 = 4f(3)=(63+6+11)mod19=4
  • f(4)=(112+8+11) mod 19=17f(4) = (112 + 8 + 11) \bmod 19 = 17f(4)=(112+8+11)mod19=17
  • f(5)=(175+10+11) mod 19=6f(5) = (175 + 10 + 11) \bmod 19 = 6f(5)=(175+10+11)mod19=6

恢复阶段(任取3个,如 f(2)=5, f(3)=4, f(5)=6):

三个子项分别计算:

f(2) 的子项:

5⋅(x−3)(x−5)(2−3)(2−5)=5⋅(x−3)(x−5)3=5⋅13⋅(x−3)(x−5)=65(x−3)(x−5) 5 \cdot \frac{(x-3)(x-5)}{(2-3)(2-5)} = 5 \cdot \frac{(x-3)(x-5)}{3} = 5 \cdot 13 \cdot (x-3)(x-5) = 65(x-3)(x-5) 5⋅(2−3)(2−5)(x−3)(x−5)=5⋅3(x−3)(x−5)=5⋅13⋅(x−3)(x−5)=65(x−3)(x−5)

f(3) 的子项:

4⋅(x−2)(x−5)(3−2)(3−5)=4⋅(x−2)(x−5)−2=4⋅9⋅(x−2)(x−5)=36(x−2)(x−5) 4 \cdot \frac{(x-2)(x-5)}{(3-2)(3-5)} = 4 \cdot \frac{(x-2)(x-5)}{-2} = 4 \cdot 9 \cdot (x-2)(x-5) = 36(x-2)(x-5) 4⋅(3−2)(3−5)(x−2)(x−5)=4⋅−2(x−2)(x−5)=4⋅9⋅(x−2)(x−5)=36(x−2)(x−5)

f(5) 的子项:

6⋅(x−2)(x−3)(5−2)(5−3)=6⋅(x−2)(x−3)6=6⋅16⋅(x−2)(x−3)=96(x−2)(x−3) 6 \cdot \frac{(x-2)(x-3)}{(5-2)(5-3)} = 6 \cdot \frac{(x-2)(x-3)}{6} = 6 \cdot 16 \cdot (x-2)(x-3) = 96(x-2)(x-3) 6⋅(5−2)(5−3)(x−2)(x−3)=6⋅6(x−2)(x−3)=6⋅16⋅(x−2)(x−3)=96(x−2)(x−3)

合并:

f(x)=65(x−3)(x−5)+36(x−2)(x−5)+96(x−2)(x−3) mod 19=(26x2−188x+296) mod 19=7x2+2x+11 \begin{aligned} f(x) &= 65(x-3)(x-5) + 36(x-2)(x-5) + 96(x-2)(x-3) \bmod 19 \\ &= (26x^2 - 188x + 296) \bmod 19 \\ &= 7x^2 + 2x + 11 \end{aligned} f(x)=65(x−3)(x−5)+36(x−2)(x−5)+96(x−2)(x−3)mod19=(26x2−188x+296)mod19=7x2+2x+11

得 f(0)=11=kf(0) = 11 = kf(0)=11=k,恢复成功。

这个演算直观地展示了:只要凑够t个点,多项式就被唯一确定了;如果只有两个点(少于3个),这个二次多项式就是不确定的------秘密信息理论上完全安全。更重要的一点是,即便攻击者拿到了系统的某些内部数据(某个 s_{i+1}),也无法反推出前一个子秘密 s_i。


总结路线

回顾整条主线:

  1. 认证是网络安全的基础------所有其他安全措施都建立在"知道在和谁通信"之上。
  2. 口令是最实际的认证方式,但它面临着嗅探、重放、钓鱼、跨站泄露等各种威胁,而且人类记忆能力的限制使得"好用"和"安全"天然对立。
  3. 口令强度评估让我们能够量化地理解:为什么有些口令看起来复杂但实际不安全,攻击者是如何利用统计规律批量猜解口令的。
  4. 认证协议设计从最简单的明文传输,一步步演变到挑战-应答、对称/非对称认证、双向认证、会话密钥建立、完全正向保密------每一步都是在对前一版的缺陷进行修补,而每一次修补都可能引入新的攻击面。
  5. DH密钥协商PFS解决了"如何在公开信道上协商密钥"以及"如何使过去会话不受未来密钥泄露影响"这两个根本性问题。
  6. 生物特征多因子认证尝试弥补口令的短板,但各有各的代价。多因子真正的精髓在于因素之间不可互相推导。
  7. 秘密共享则是从另一个维度思考信任:不是相信一个人,而是相信一群人中的足够多数。Shamir方案用多项式插值这个纯数学工具实现了这个目的,简洁而深刻。