ARTICLE · INTELLIGENCE

战地情报 · 详情页

来自尧图项目组的一线实战观察与深度解析

协议与应用基础(一):密码协议到底在解决什么问题

协议与应用基础(一):密码协议到底在解决什么问题 协议与应用基础一密码协议到底在解决什么问题前言一、密码原语和密码协议不是一回事1.1 密码原语解决局部问题1.2 算法安全不等于协议安全二、先明确安全目标2.1 机密性2.2 完整性2.3 身份认证2.4 新鲜性与防重放2.5 密钥确认2.6 前向安全性2.7 可否认性与不可否认性三、先建立威胁模型3.1 攻击者能做什么3.2 端点和密钥假设3.3 参与者、角色和密钥类型四、协议消息必须绑定正确的上下文4.1 不能只保护“消息内容”4.2 Transcript hash4.3 方向和角色分离4.4 编码必须唯一五、几个典型的不安全协议5.1 直接传输口令5.2 只有挑战没有绑定身份5.3 裸 Diffie-Hellman5.4 只加密不认证5.5 先解密再决定是否验证六、协议状态机安全不只在公式里6.1 消息顺序6.2 错误状态和失败关闭6.3 状态和密钥必须同步七、密钥派生和 nonce 管理7.1 共享秘密不是业务密钥7.2 AEAD nonce 不能重复7.3 nonce、challenge、IV 不是同一个概念八、如何系统分析一个密码协议8.1 列出参与者和长期密钥8.2 写出完整消息流8.3 对每个字段问三个问题8.4 检查攻击面8.5 最后检查实现细节九、密码协议的分层理解十、常见误区10.1 选择了强算法协议就安全10.2 加密等于认证10.3 发送随机数就能防重放10.4 ECDH 自动认证对方10.5 失败消息不属于协议10.6 一个密钥到处复用十一、总结前言前面的公钥密码基础系列介绍了 RSA、Diffie-Hellman、ECC、ECDH、ECDSA、SM2、数字证书和 PKI。这些内容解决了“如何进行数学运算”的问题但真实系统还要面对一个更大的问题多个参与者如何按照明确的步骤使用这些密码原语达到完整的安全目标这就是密码协议要解决的问题。密码协议不是把几个算法简单拼在一起而是对以下内容作出精确定义谁和谁通信每一方知道什么、持有什么攻击者可以观察、修改、延迟和重放什么哪一步产生密钥哪一步验证身份消息如何绑定到会话、身份和用途出错后系统进入什么状态最终需要保证什么安全性质。例如ECDH 可以让双方计算同一个共享点但裸 ECDH 没有解决“对方是谁”的问题数字签名可以认证消息来源但没有自动解决会话密钥派生和重放问题AES-GCM 可以保护数据包但不会自动建立双方都知道的会话密钥。本文先不深入某一个具体协议而是建立阅读、设计和分析密码协议时通用的框架为后续学习 TLS、认证协议、密钥交换、设备注册和安全通信协议打基础。密码协议中的示例只用于教学。真实系统应优先采用成熟标准和经过审计的密码库不要根据示例自行设计生产协议。现代密码学 专栏https://blog.csdn.net/r_feynman_/category_13190241.htmlCrypto 密码解析实战靶场https://blog.csdn.net/r_feynman_/category_13194584.html一、密码原语和密码协议不是一回事1.1 密码原语解决局部问题常见密码原语可以分别完成局部任务原语主要功能不能自动解决的问题哈希函数固定长度摘要、承诺、完整性组件不提供密钥保密和身份认证MAC共享密钥下的完整性与认证不解决密钥如何分发也不提供公开可验证性数字签名私钥持有者对消息的公开认证不提供消息机密性也不自动防重放对称加密保护消息机密性不负责身份验证和密钥协商AEAD同时提供机密性和完整性仍需要安全密钥和 nonce 管理DH/ECDH建立共享秘密裸协议不认证对方也不自动派生业务密钥KDF从共享秘密派生用途明确的密钥不产生原始共享秘密也不验证对端身份安全协议需要把这些局部能力组合成完整流程。例如一个典型的安全通信协议可能包含通过证书或预共享密钥认证对方通过 ECDHE 建立临时共享秘密通过 KDF 派生握手密钥和应用数据密钥通过 transcript hash 绑定整个握手过程通过 AEAD 保护后续数据通过序列号、nonce 和状态机防止重放和乱序。1.2 算法安全不等于协议安全单独看每个算法都可能是安全的组合方式错误协议仍然可能失败。例如使用安全的 ECDH但接受未经验证的公钥可能遭受中间人或小子群攻击使用安全的 AES-GCM但重复 nonce可能破坏机密性和完整性使用安全的签名但签名没有覆盖会话参数攻击者可能进行降级或未知密钥共享攻击使用安全的密码哈希但登录接口没有限速仍然容易被在线猜测使用安全的证书但关闭主机名验证攻击者仍可能冒充其他服务。因此分析协议时不能只问“用了什么算法”还要问“算法到底保护了哪一段数据、由谁验证、验证结果如何影响状态”。二、先明确安全目标设计或分析协议前必须把“安全”拆成可验证的目标。不同应用需要的目标可能不同不能笼统地写成“保证安全”。2.1 机密性只有授权参与者可以读取消息内容。例如M → 加密 C M\xrightarrow{\text{加密}}CM加密​C攻击者可以看到密文C CC但不能在可行计算资源内恢复M MM。机密性还要明确保护范围是保护单条消息、整个会话还是历史会话如果长期私钥日后泄露过去的会话是否仍然安全后一个问题就是前向安全性的一部分。2.2 完整性攻击者不能在不被发现的情况下修改消息。仅仅“消息还能解密”不代表完整性成立必须有 MAC、AEAD 标签或数字签名等验证机制。2.3 身份认证通信双方需要确认对方身份。认证可以有不同层次认证某个长期公钥的持有者认证某个域名或设备认证用户口令的持有者认证消息确实由某个实体生成。“消息来自持有密钥的人”和“这个密钥属于名为 Bob 的人”不是同一件事。后者还需要证书、预共享身份数据库或其他信任绑定。2.4 新鲜性与防重放攻击者即使不能伪造消息也可能把过去的合法消息重新发送。协议需要判断当前消息是否属于本次会话常用手段包括随机挑战值 nonce时间戳和有效窗口单调计数器会话编号序列号和状态机。仅仅使用随机数并不自动防重放。接收方还必须保存或绑定该随机数确保旧消息不会被当作新消息再次接受。2.5 密钥确认密钥交换双方可能都计算出一个值但一方未必知道对方也计算出了同一个值。密钥确认消息可以让双方确认对方拥有预期的私钥双方使用了相同的会话参数没有发生中间人替换或协议分叉。2.6 前向安全性如果长期私钥未来泄露过去已经结束的会话是否仍然保密使用每次会话都不同的临时 ECDHE 私钥结合安全删除和完整握手绑定可以提供前向安全性。2.7 可否认性与不可否认性不同协议对签名证据的要求不同使用共享 MAC 时通信双方都知道同一个密钥第三方通常无法判断是哪一方生成了消息具有一定可否认性使用数字签名时只有签名者拥有私钥第三方可以公开验证适合需要公开证明的场景。这不是“签名一定比 MAC 更安全”而是安全目标不同。三、先建立威胁模型3.1 攻击者能做什么密码协议通常假设攻击者控制网络但不一定控制端点。攻击者可能监听全部通信修改、删除、延迟和重排消息复制合法消息并重放伪造源地址、连接和握手顺序同时与多个参与者建立会话诱导不同协议或不同版本之间互相解析消息观察错误响应、时间差和流量模式。这种攻击者常被称为 Dolev-Yao 风格的主动网络攻击者。协议如果只在“被动监听者”模型下安全面对主动修改和重放可能完全失效。3.2 端点和密钥假设还需要明确私钥是否安全保存CA 或预共享密钥数据库是否可信随机数生成器是否安全操作系统时间是否可信端点是否可能被恶意软件控制密码库是否存在侧信道或内存泄露。协议无法弥补“私钥已经被攻击者拿走”这一事实。好的协议会尽量缩小密钥泄露影响但不会魔法般恢复被完全控制的端点。3.3 参与者、角色和密钥类型协议文档应明确写出角色发起方 Alice响应方 Bob认证服务、CA 或 KDC中继或代理被动观察者和主动攻击者。还要区分长期身份密钥临时会话密钥加密密钥MAC 密钥签名密钥密钥封装或密钥加密密钥。把同一把密钥用于多个用途可能导致跨协议和跨方向攻击。KDF 输出应按标签分离用途例如K c l i e n t _ w r i t e KDF ⁡ ( Z , “client write key” ) K_{client\_write}\operatorname{KDF}(Z,\text{“client write key”})Kclient_write​KDF(Z,“client write key”)K s e r v e r _ w r i t e KDF ⁡ ( Z , “server write key” ) K_{server\_write}\operatorname{KDF}(Z,\text{“server write key”})Kserver_write​KDF(Z,“server write key”)四、协议消息必须绑定正确的上下文4.1 不能只保护“消息内容”假设客户端发送amount100toBob如果 MAC 只覆盖金额和收款人却没有覆盖账户、方向、会话和序列号攻击者可能把一条合法消息复制到另一个上下文中。更完整的认证输入通常包含Tag ⁡ MAC ⁡ K ( version ∥ role ∥ session ∥ seq ∥ type ∥ M ) \operatorname{Tag}\operatorname{MAC}_K(\text{version}\|\text{role}\|\text{session}\|\text{seq}\|\text{type}\|M)TagMACK​(version∥role∥session∥seq∥type∥M)具体字段取决于协议但核心原则是凡是会影响解释结果的字段都要绑定进认证范围。4.2 Transcript hash现代握手协议通常计算整个握手消息的哈希T H ( m 1 ∥ m 2 ∥ ⋯ ∥ m t ) TH(m_1\|m_2\|\cdots\|m_t)TH(m1​∥m2​∥⋯∥mt​)然后让签名、Finished MAC 或密钥派生依赖T TT。这样攻击者就不能随意替换协议版本密码套件密钥交换组身份信息扩展字段对端临时公钥。只签名“我支持某个公钥”而不签名完整上下文可能允许攻击者把同一签名搬到另一个会话中。4.3 方向和角色分离同一密钥同时用于客户端到服务器和服务器到客户端会增加反射攻击风险。通常应通过 KDF 标签派生不同方向的密钥K A → B ≠ K B → A K_{A\to B}\ne K_{B\to A}KA→B​KB→A​消息也应显式携带或隐含绑定发送方、接收方和角色。协议状态机不能只根据“收到了一条合法 MAC 的消息”就接受而要确认它出现在正确的方向和正确的阶段。4.4 编码必须唯一如果同一个逻辑消息可以有多种字节表示攻击者可能利用解析器差异制造签名或 MAC 绕过。协议应规定字段顺序长度编码字节序字符编码是否允许前导零整数和字符串的边界空字段和重复字段的处理。签名和加密保护的是字节串不是“人眼理解的对象”。双方对同一对象采用不同编码验证就会失败更危险的是双方都接受不同编码但解释结果不同。五、几个典型的不安全协议5.1 直接传输口令最简单的登录协议是Client - Server: username, password Server - Client: success / failure如果没有安全传输层窃听者可以直接获取口令。即使加密了传输服务器若直接保存口令也会在数据库泄露时造成大规模风险。更合理的口令认证通常需要安全传输服务器端使用口令哈希和独立盐值限速、锁定和异常检测多因素认证或 PAKE 等方案避免详细错误信息暴露账户状态。5.2 只有挑战没有绑定身份服务器发送随机挑战N NN客户端返回MAC ⁡ K ( N ) \operatorname{MAC}_K(N)MACK​(N)这可以证明响应者知道共享密钥但如果协议没有绑定用户名、服务名和会话上下文攻击者可能把响应搬到另一个服务或另一个角色中。更完整的输入可以是MAC ⁡ K ( server ∥ client ∥ service ∥ N ∥ session_id ) \operatorname{MAC}_K(\text{server}\|\text{client}\|\text{service}\|N\|\text{session\_id})MACK​(server∥client∥service∥N∥session_id)5.3 裸 Diffie-HellmanAlice 和 Bob 交换A g a , B g b Ag^a,\qquad Bg^bAga,Bgb然后计算g a b g^{ab}gab。如果没有签名、证书或预共享身份Mallory 可以替换A AA和B BB分别与两边建立密钥。这是最典型的“密钥交换成功但身份认证失败”。5.4 只加密不认证如果使用可篡改的加密模式攻击者可能修改密文而不被发现。现代协议通常使用 AEAD把机密性和完整性放到统一接口中并把 nonce、附加认证数据和密文格式严格定义。5.5 先解密再决定是否验证如果解密端在验证 MAC/Tag 之前把部分明文交给上层攻击者可能利用错误响应、时序差异或解析副作用构造解密预言机。正确流程通常是解析格式并检查边界验证认证标签认证成功后再接受明文对失败统一处理避免泄露过多信息。六、协议状态机安全不只在公式里6.1 消息顺序协议必须定义每个状态允许收到什么消息。例如START - ClientHello WAIT_SERVER - ServerHello, Certificate, Finished SEND_CLIENT_FINISHED - ApplicationData CLOSED如果实现允许在认证完成前处理业务数据攻击者可能绕过握手。若允许重复接收已经处理过的消息也可能发生重放或状态回退。6.2 错误状态和失败关闭失败处理也属于协议的一部分签名验证失败后是否继续尝试其他算法收到未知扩展时是拒绝还是忽略计数器溢出时如何处理认证失败是否允许无限重试连接关闭后是否还能复用密钥。错误路径往往比成功路径更少被测试却经常成为攻击入口。6.3 状态和密钥必须同步握手密钥、应用密钥和旧密钥的生效范围应明确。常见错误包括一方已经切换密钥另一方仍使用旧密钥重连时复用旧会话 nonce会话恢复时没有重新绑定新参数关闭连接后仍接受旧序列号密钥更新消息没有被当前密钥保护。协议应写清楚每个密钥在哪个状态生效、何时删除、失败后是否回滚。七、密钥派生和 nonce 管理7.1 共享秘密不是业务密钥DH/ECDH 输出通常是高熵共享秘密但不应直接作为所有用途的统一密钥。使用 KDF 可以派生多个独立密钥区分发送方向区分握手和应用数据绑定协议版本和会话上下文固定输出长度和密钥格式。抽象流程为Z KeyAgreement ⁡ ( s k A , p k B ) Z\operatorname{KeyAgreement}(sk_A,pk_B)ZKeyAgreement(skA​,pkB​)K 1 , K 2 , … KDF ⁡ ( Z , context ) K_1,K_2,\ldots\operatorname{KDF}(Z,\text{context})K1​,K2​,…KDF(Z,context)7.2 AEAD nonce 不能重复对 AES-GCM、ChaCha20-Poly1305 等 AEADnonce 通常不要求保密但必须满足协议规定的唯一性要求。可以使用每条连接独立的随机初始值加序列号单调计数器密钥更新后重新开始计数把方向和记录序号纳入 nonce 构造。如果同一密钥下重复 AEAD nonce攻击者可能恢复明文关系甚至破坏认证安全。协议必须定义连接建立、重传、并发和密钥更新时如何保证唯一性。7.3 nonce、challenge、IV 不是同一个概念这些词都可能被翻译成“随机数”或“随机向量”但作用不同nonce通常强调一次性或唯一性challenge用于证明新鲜性可能由验证方生成IV加密模式的初始化输入安全要求依算法而异salt通常用于 KDF 或口令哈希不一定需要保密签名 noncek kk必须安全、不可预测重复可能泄露私钥。协议文档应明确每个随机量的生成者、长度、唯一性、保密性和使用范围。八、如何系统分析一个密码协议拿到一段协议描述时可以按以下步骤分析。8.1 列出参与者和长期密钥先写出参与者是谁每个参与者预先知道什么谁拥有 CA 签发的证书哪些密钥长期存在哪些值由攻击者控制。8.2 写出完整消息流不要只看“核心公式”把每一条消息写出来包括随机数公钥证书签名MAC/Tag会话编号版本和算法选择错误响应。8.3 对每个字段问三个问题谁生成它谁验证它它绑定了哪些上下文如果某字段会影响安全决策却没有被签名、MAC 或 transcript hash 覆盖就是重点审计对象。8.4 检查攻击面至少尝试思考中间人替换重放反射降级未知密钥共享小子群或非法公钥nonce 重用解析器差异错误响应和时序泄露连接跨会话或跨角色复用。8.5 最后检查实现细节是否使用经过审计的密码库是否禁用了过时算法是否常数时间是否安全清除密钥是否有重试和并发问题是否记录了足够的审计信息但没有泄露秘密是否对证书、编码和边界做严格验证。九、密码协议的分层理解可以把一个完整安全通信系统拆成以下几层原语层哈希、MAC、AEAD、签名、DH/ECDH、KDF 等数学构件。密钥层密钥生成、分发、协商、派生、轮换、撤销和销毁。消息层字段编码、长度、顺序、序列号、nonce、认证范围和错误处理。会话层握手、身份认证、协议版本、密码套件、状态机和密钥更新。应用层用户身份、权限、业务操作、审计、重试、幂等性和数据格式。很多事故来自层间假设不一致底层认为“已经认证了公钥”应用却没有检查主机名传输层认为“消息完整”应用却允许重复执行转账密码库认为 nonce 唯一业务层却在重试时复用了同一记录。十、常见误区10.1 选择了强算法协议就安全算法只是构件。密钥管理、身份绑定、消息顺序和错误处理同样重要。10.2 加密等于认证很多可逆加密模式不提供完整性。现代通信应优先使用 AEAD 或“加密 认证”经过审计的组合。10.3 发送随机数就能防重放随机数必须被正确绑定和记录。服务器如果不保存挑战状态旧响应仍可能被接受。10.4 ECDH 自动认证对方裸 ECDH 只建立共享秘密不证明公钥属于谁。认证需要证书、签名、预共享密钥或其他身份绑定。10.5 失败消息不属于协议错误码、关闭顺序、重试次数和时序差异都可能泄露状态或形成攻击入口必须纳入协议设计。10.6 一个密钥到处复用不同方向、不同会话、不同算法和不同协议应通过 KDF 标签派生独立密钥避免跨用途攻击。十一、总结密码协议的核心不是“把 RSA、ECC、AES 和哈希放在一起”而是明确回答谁在和谁通信对手能够做什么哪些身份和密钥已经被信任消息如何绑定会话和上下文如何防止重放、降级、中间人和跨协议攻击发生错误时系统如何安全停止。一个常见的安全通信主线是身份认证 临时密钥交换 KDF AEAD 状态机 \text{身份认证}\text{临时密钥交换}\text{KDF}\text{AEAD}\text{状态机}身份认证临时密钥交换KDFAEAD状态机其中每一项都只解决一部分问题必须通过明确的消息格式、transcript hash、方向分离、nonce 管理和生命周期控制组合起来。下一篇将把这些原则放进真实使用最广泛的安全通信协议之一TLS。我们会对比 TLS 1.2 和 TLS 1.3 的握手流程观察证书、ECDHE、签名、HKDF 和 AEAD 如何在一个完整协议中协同工作。
RELATED READING

延伸阅读

更多一线实战笔记与深度复盘,助您持续精进