3. LE Secure Connections:ECDH密钥交换、密钥生成、安全连接升级流程

LE Secure Connections,说白了就是蓝牙4.2以后引入的一套全新安全架构。我最早接触它是在做一款医疗手环项目时,客户要求数据必须经过P256椭圆曲线加密——嗯,那时候我才真正开始啃这套协议。

这一节我们聚焦三个核心问题:密钥怎么交换的?最终生成了哪些密钥?以及从普通连接升级到安全连接的完整流程。

3.1 ECDH密钥交换:双方如何协商出共享密钥?

传统蓝牙的配对依赖PIN码或OOB数据,本质上是一种预共享密钥模式。而LE Secure Connections用的是椭圆曲线Diffie-Hellman(ECDH),它让双方在不传递私钥的情况下,计算出同一个共享密钥。

具体过程是这样的:

  1. 生成密钥对:Master和Slave各自生成一个P-256椭圆曲线密钥对(私钥+公钥)。
  2. 交换公钥:双方通过Pairing Request/Response之后的Pairing Public Key包,把自己的公钥发给对方。
  3. 计算共享密钥:各自用对方的公钥和自己的私钥,执行ECDH运算,得到DHKey(Diffie-Hellman共享密钥)。

核心公式(理解即可):

DHKey = P256(SKa, PKb) = P256(SKb, PKa)

其中SKa是A的私钥,PKb是B的公钥。两边算出来的DHKey是完全一样的。

我在项目中遇到过一个问题:公钥交换时如果被中间人篡改,双方算出的DHKey就不一致。所以LE Secure Connections在后续的Authentication Stage 1里,会用Numeric Comparison或Passkey Entry等方式验证公钥的真实性。这一点后面会细讲。

3.2 密钥生成:从DHKey到最终使用的加密密钥

DHKey只是一个256位的共享秘密,不能直接用来加密。蓝牙协议定义了一套密钥派生函数(f1~f5),把DHKey和配对过程中交换的随机数、地址等信息揉在一起,生成最终使用的密钥。

我习惯把这套流程称为“密钥烘焙”——原料是DHKey,辅料是各种随机数,烤出来的是LTK、IRK等成品。

函数 输入 输出 用途
f1 DHKey, SKa, SKb, Na, Nb, IOcapA, IOcapB MConfirm / NConfirm 配对确认值(Authentication Stage 1)
f2 DHKey, Na, Nb, AAddr, BAddr MacKey, LTK 生成长期密钥LTK和MAC密钥
f3 DHKey, Na, Nb, AAddr, BAddr IRK 身份解析密钥(用于私密地址)
f4 DHKey, Na, Nb, AAddr, BAddr CSRK 连接签名解析密钥
f5 DHKey, Na, Nb, AAddr, BAddr IV, SK 生成会话密钥SK和初始向量IV

避坑指南:我曾经在移植协议栈时,发现f2和f5的输入参数顺序搞反了,导致LTK和Session Key对不上。建议你在实现时,对照Core Spec Vol.3 Part H Section 2.2.7的伪代码逐行核对。

3.3 安全连接升级流程:从无加密到加密通信

整个升级过程可以分成四个阶段。我画了一张流程图,方便你理解整体脉络。

LE Secure Connections 安全升级流程 Phase 1: 配对特征交换 IO能力 / OOB / 密钥大小 Phase 2: ECDH密钥交换 公钥交换 + DHKey计算 Phase 3: 认证阶段1 Numeric Comparison / Passkey Entry Phase 4: 密钥派生 f2~f5 → LTK / IRK / SK 加密启动 LL_ENC_REQ / LL_ENC_RSP 关键说明: • Phase 3 的认证方式取决于IO能力 • Numeric Comparison:显示6位数字,用户确认 • Passkey Entry:一方输入,另一方显示

3.4 认证阶段1的三种模式

Phase 3是整个流程中最容易出问题的环节。根据双方的IO能力,蓝牙协议定义了三种认证方式:

  • Numeric Comparison(数值比较):双方显示一个6位数字,用户确认是否一致。这是最常见的方式,适合有显示屏和确认按钮的设备。
  • Passkey Entry(密码输入):一方显示数字,另一方输入。适合键盘类设备。
  • Out of Band(带外):通过NFC或其他带外通道交换确认值。适合无UI的设备。

注意:如果双方都没有显示屏和输入能力(比如两个传感器),则只能使用Just Works模式。这种模式下认证阶段1被跳过,无法抵抗中间人攻击。我在做工业传感器项目时,就因为这个被安全审计打回了一次——后来加了NFC OOB才通过。

3.5 密钥派生的实际顺序

Phase 4的密钥派生不是一次完成的。我整理了一个典型的执行顺序:

  1. f2函数:先生成MacKey和LTK。MacKey用于后续的密钥分发消息认证。
  2. f3函数:生成IRK,用于私密地址解析。
  3. f4函数:生成CSRK,用于连接签名。
  4. f5函数:生成Session Key SK和初始向量IV,用于当前连接的加密。

这里有个细节:LTK和SK是不同的。LTK是长期密钥,存储在非易失性存储器中,用于下次重连时的快速配对。SK是会话密钥,每次连接都会重新生成,用完即弃。

我的经验:在实现密钥存储时,建议把LTK、IRK、CSRK分开存储。我曾经见过一个方案把所有密钥拼成一个结构体存储,结果升级固件时结构体对齐方式变了,导致密钥读取失败——设备再也连不上了。

3.6 加密启动:最后一步

密钥派生完成后,Master发送LL_ENC_REQ,携带用SK加密的随机数。Slave回复LL_ENC_RSP。双方确认加密参数无误后,链路层开始用AES-CCM加密所有数据包。

嗯,到这里,一条安全的BLE连接才算真正建立起来。