密码学 21:VPN 的密钥怎样建立——IKEv2、IPsec 与安全关联
一台开发机经 VPN 访问测试网络中的 HTTPS RPC,使用钱包提交一笔无价值交易。出现三个“连接安全”的说法:VPN 已连接,HTTPS 握手成功,交易签名验过。它们保护的对象并不相同。VPN 先解决“这两个网络端点如何商定保护哪些 IP 包、用哪些方向的密钥”,不能因此替钱包签交易,也不保证远端 RPC 给出的区块状态可信。
先把通道建立者与数据保护者分开
IKEv2(RFC 7296)协商 IPsec 安全关联;ESP(RFC 4303)保护落到相应关联上的数据包。一个安全关联,简称 SA,不是一张写着“本 VPN 全部通信都安全”的通行证:它包含标识、算法、密钥、方向、序号等状态;可保护的流量还受流量选择器与路由影响。IKE 自己的 IKE SA 保护后续控制消息;给数据包用的是 Child SA。ESP 双向流量通常使用两条方向不同的 SA。
1 | |
第一对 IKE_SA_INIT 消息交换临时密钥材料和两个随机 nonce,此时尚不能因为 DH 算出了相同秘密就认定对端身份。第二对 IKE_AUTH 消息将身份和认证方法(如证书签名或合适的共享秘密)绑定到之前交换,才建立面向期望对端的 IKE SA,并创建首个 Child SA。若删除这一步身份绑定,攻击者可分别与两侧做密钥交换,在两侧呈现不同的“双方已协商秘密”,正是 10 中的中间人问题。IKE 有自己的请求/响应 Message ID;别把它当作 ESP 的每包序号。
从共享秘密到两种 SA 的密钥
RFC 7296 §2.14 给出核心关系。用 Ni、Nr 表示两端的 nonce,g^ir 表示本次临时 DH 的共享值,SPIi、SPIr 是 IKE SA 两端各自选的标识。实际字节类型和长度要依协商的 PRF 与变换编码,图中的串接仅标明哪些输入进入派生。
1 | |
输出的分段长度由具体协商算法决定。采用组合模式的 PRF/加密/完整性算法配置与 AEAD 配置可能不同;不能据这张图盲目为每个名字截取相同字节数并安装生产 SA。后续创建 Child SA 可以不再做 DH,若需要相对于旧 IKE SA 密钥材料的额外独立前向保密,就要检视新交换是否包含新的 DH。KDF 不创造输入缺少的熵;对固定的 g^ir 和固定 nonces 重算得到同样结果,并不说明系统已获得新随机性。
IKE SA 的 SPI 和 ESP SA 的 SPI 也不是一个字段:前者在 IKE 报文头中是 8 字节,后者在 ESP 包头中为 4 字节。SPI 帮接收者找到对应安全关联及密钥;它不是签名,也不是业务订单号。ESP 的数据包序号服务于每条接收 SA 的防重放窗口。接收端要实际启用对应防重放处理,并配合完整性保护,才可拒绝同一 SA 上被复制的旧包;有序号字段并不自动阻止攻击者发送两次不同但都有效的业务请求。业务层订单唯一 ID 和链上交易 nonce 仍各管各的状态。
一个小实验能证明什么,不能证明什么
examples/cryptography/21_ike_keymat.py 将公开的 RFC 7748 §6.1 X25519 测试密钥交给 cryptography==50.0.2 计算真实原语输出。然后以公开、固定的教学 nonce 与 SPI,用标准库 HMAC-SHA256 充当本例选定的 PRF,按 RFC 7296 的派生表达式计算 SKEYSEED、首段 SK_d 和 Child KEYMAT。不输出它们的值,也不把固定教学 nonce 当作真实协议应使用的随机 nonce。更改 Ni 或 SPIi,SK_d 与原输入不同;更改 Ni,首个 Child KEYMAT 也不同。
脚本另用内存集合记录“1 号包”是否已经出现,作为接收方需保存消费状态的最小教学模型。第一包可接受,完全相同编号的第二次被拒;这个集合没有 SPI 查表、滑动窗口、扩展序号、包的 AEAD 验证,所以不是 ESP 实现或真实防重放协议实验。
先按仓库内 examples/cryptography/README.md 完成环境准备;以下命令从仓库根目录执行。
1 | |
这是隔离 venv 的本次路径。2026-10-06 UTC 两条命令退出码为 0、1 项测试通过;公开输出明确 real_ike_or_esp_executed=false。当前环境没有 ip、swanctl 或 strongswan,进程也没有网络管理权限;没有建起 VPN、执行 IKE_AUTH、安装 SA 或抓取 ESP 包。真正验收这些行为需要在授权的隔离网络里装两端组件、冻结版本与配置,验证证书/共享密钥错误身份失败及实际 ESP 重放拒绝;不能把运行派生脚本当成那份证据。
在贯穿场景里,还要观察 VPN 保护到哪一个网关:若它在网关处终止,网关到 HTTPS RPC 的下一段是否受保护取决于后续配置。HTTP 请求如经 HTTPS 再建 TLS,TLS 验的是 RPC 服务身份与通信;交易签名验的是交易授权字节。VPN、HTTPS 或交易验签的任何一项成功,都不意味着交易已执行、进入可信区块或现实订单已交付。
两道带答案的练习
推导题: 画三层:IKE 控制消息、Child SA 上的 ESP 包、HTTPS RPC 上的钱包交易。分别标明双向谁持有密钥、接收方依什么查找密钥。删除 IKE_AUTH 身份认证、删除 ESP 接收方消费序号状态时,分别出现哪一种攻击?
可核对答案: 两端的 IKE SA 具有按方向分开的密钥,控制消息依 IKE SPI 等状态处理;两条 ESP SA 各有单方向密钥,入站包以 SPI(及上下文)匹配 SA;HTTPS 另有 TLS 握手密钥,钱包交易私钥只应留在钱包。没有 IKE_AUTH,主动攻击者可分别 DH 与两边冒充对端;没有实际的 ESP 防重放状态,旧的、仍可验的同 SA 包可被复制到接收侧。ESP 防重放不替代业务订单或交易 nonce。
实验变更题: 将 21_ike_keymat.py 中 INITIATOR_NONCE 的第一字节从 a1 改为 00,再将教学 accept_once 对重复包号的判断删除。分别预测哪两个独立的正例会失败;是否由此测到真实 ESP 的重放处理?
可核对答案: 第一处会改变 SK_d、Child KEYMAT,相对原固定输入的差异断言需要相应改造“对照 nonce”才有意义;若把 INITIATOR_NONCE 本身也改成对照用的值,nonce_changes_sk_d 应失败。第二处导致重复 1 号包也被接受,teaching_replay_model_second_rejects 应失败。两者都是教学模型与原语级变化,真实 IKE/ESP 项仍为 NOT_RUN。
资料与导航
- RFC 7296 §1.2–§1.3、§2.14–§2.17:握手、AUTH、两类 SA 的派生与换钥。
- RFC 4303 §2–§3:ESP SPI、序号、完整性与接收方防重放规则。
- RFC 8247:IKEv2 算法要求更新;本文未将历史原语列为推荐生产配置。
- 10 两端如何得到共同秘密 · 18 mTLS 与 TLS 终止 · 20 SSH 为何有主机密钥和登录密钥。






