安全机制

BLE Privacy 隐私机制详解:RPA、IRK 与解析列表

发布于 2026-07-21 · 来自「嵌入式江湖」技术专栏

BLE 设备在广播和连接时,空口里会携带自己的设备地址。如果这个地址是固定不变的,任何人拿一部手机、开一个扫描 App,就能在商场、地铁、写字楼里长期追踪某个特定设备(进而追踪它的主人)。BLE Privacy(隐私特性)就是为了对抗这种"地址追踪"而生的一整套机制:让设备对外使用一个会定时变化、且只有"认识它的人"才能还原真身的地址——RPA(Resolvable Private Address,可解析私有地址)。

这篇文章把 Privacy 从"为什么需要"到"控制器怎么实现"讲清楚,包括 IRK、解析列表(Resolving List)、两种隐私模式、RPA 超时、以及一堆实战里会踩的坑。

一、地址追踪:Privacy 要解决的问题

先理解威胁模型。一个 BLE 设备(比如智能手环、耳机、手机)在未连接时会周期性发广播包,广播包里带 AdvA(广播者地址)。如果 AdvA 是一个固定的 Public 地址或 Static Random 地址

  • 攻击者在 A 地点记录到地址 AA:BB:CC:11:22:33
  • 一小时后在 B 地点又扫到同一个地址
  • → 攻击者就知道"这个设备(这个人)从 A 移动到了 B"

这就是被动追踪(passive tracking)。它不需要连接、不需要配对,只要静静地扫描广播即可。早年很多可穿戴设备、iBeacon、甚至手机都因为固定 MAC 被用于商场客流分析和轨迹追踪。

Privacy 的核心思路:对外暴露的地址要经常换,而且换了之后,陌生人看不出"新地址"和"旧地址"是同一台设备,但已经和它绑定过的对端(存了它的 IRK)依然能认出来。

二、地址类型回顾:RPA 属于哪一类

BLE 地址分两大类(详见《BLE 设备地址 BD_ADDR 科普》),这里只聚焦隐私相关的:

地址类型 高 2 bit 是否变化 隐私性
Public 不变 无(可被长期追踪)
Static Random 11 上电周期内不变 弱(一次开机内可追踪)
Non-Resolvable Private (NRPA) 00 定时变 强,但对端也认不出(少用)
Resolvable Private (RPA) 10 定时变 强,且对端可解析 ← Privacy 主角

RPA 就是 Privacy 机制产生的地址:对陌生人是随机噪声,对"老朋友"可还原

三、RPA 的结构与生成

RPA 是一个 48 位地址,由两部分组成:

| 47                24 | 23                 0 |
|        hash          |        prand         |
|      (24 bit)        |       (24 bit)        |
  • prand:24 位随机数,但最高 2 bit 固定为 10(标识这是 RPA)。剩下 22 位是真随机。
  • hash:24 位,由密钥 IRK 和 prand 计算得到:
hash = ah(IRK, prand)

其中 ah 是蓝牙规范定义的一个基于 AES-128 的哈希函数(本质是 AES-128(IRK, padding||prand) 取低 24 位)。

关键点: - 只有持有该设备 IRK(Identity Resolving Key,身份解析密钥) 的人,才能用同样的 ah 重新算一遍,验证 hash 是否匹配,从而确认"这个变化的 RPA 就是我认识的那台设备"。 - 每次换地址,prand 变 → hash 跟着变 → 整个 48 位地址全变,陌生人看不出关联。

生成一个 RPA(伪代码)

// prand: 24 bit,最高两 bit 置为 0b10
uint8_t prand[3];
rng_fill(prand, 3);
prand[2] = (prand[2] & 0x3F) | 0x40;   // 高2bit = 10

// hash = ah(IRK, prand),取 AES128 结果低 24 bit
uint8_t hash[3];
ah(irk /*16B*/, prand /*3B*/, hash /*out 3B*/);

// 组装 RPA(小端在空口,这里按逻辑地址排列)
// RPA[47:24] = hash, RPA[23:0] = prand

解析一个 RPA(对端做的事)

收到一个 RPA 后,对端遍历自己解析列表里存的每个 IRK:

for (each irk in resolving_list) {
    uint8_t local_hash[3];
    ah(irk, rpa.prand, local_hash);
    if (memcmp(local_hash, rpa.hash, 3) == 0) {
        // 命中!这个 RPA 属于 irk 对应的那台设备
        return matched_identity;
    }
}
return NOT_RESOLVED;   // 陌生设备

四、IRK:身份的钥匙

IRK 是 Privacy 的核心密钥,它决定了"谁能认出我"。

  • IRK 是 128 位密钥,在配对/绑定的密钥分发阶段由 SMP 交换(详见《BLE SMP 过程详解》第五、六节的 Key Distribution)。
  • 每台设备有自己的 IRK,和它的 Identity Address(身份地址,即真名) 绑定。
  • 绑定时,设备把 (IRK, Identity Address) 发给对端;对端存进绑定库/解析列表。
  • 之后设备用 IRK 生成 RPA 对外广播;对端用存下来的 IRK 解析。

所以"手机地址天天变,但耳机还能秒回连"的原因就是:耳机绑定时存了手机的 IRK,每次都能把手机变化的 RPA 解析回它的真身。

特殊:IRK 全 0 是合法的"约定",表示"我不用 RPA,请用我的 Identity Address 认我"。

五、解析列表(Resolving List)与控制器辅助隐私

RPA 的生成和解析可以放在 Host(主机层,软件) 做,也可以放在 Controller(控制器,芯片底层) 做。现代方案几乎都用 Controller-based Privacy(LL Privacy,链路层隐私),因为:

  • 广播/扫描/连接的地址处理都在链路层实时发生,放控制器里做解析延迟最低、最省功耗;
  • Host 不必被每一个广播包唤醒去做 AES 解析。

控制器里维护一张 Resolving List(解析列表),每个条目包含:

{
  Peer Identity Address (对端真名) + Address Type,
  Peer IRK   (解析对端 RPA 用),
  Local IRK  (生成本机 RPA 用)
}

对应的 HCI 命令(主机配置控制器):

  • LE Add Device To Resolving List
  • LE Remove Device From Resolving List
  • LE Clear Resolving List
  • LE Set Address Resolution Enable(总开关)
  • LE Set Resolvable Private Address Timeout(设置 RPA 超时)

启用后,控制器: - 收包时:自动把对端 RPA 解析成 Identity Address 再上报给 Host(Host 看到的是稳定真名,不用管地址在变); - 发包时:自动用 Local IRK 生成本机 RPA 填进 AdvA/InitA

六、RPA 超时(Timeout)

RPA 不是每个包都换,而是每隔一段时间换一次,由 RPA Timeout 控制:

  • 规范默认 900 秒(15 分钟);可配置范围 1 秒 ~ 1 小时多。
  • 超时到了,控制器自动重新生成一个新 RPA。
  • 太短:换得勤,隐私更好,但功耗略增、且频繁变化可能影响某些交互;
  • 太长:一个地址暴露时间长,追踪窗口变大。

坑:RPA 只在下一次广播/扫描/发起连接开始时才会用上新值,不是到点立刻在空口生效。已经在进行的连接不会因为超时而换地址。

七、两种隐私模式:Device Privacy vs Network Privacy

Bluetooth 4.2 引入了两种隐私模式(Privacy Mode),针对解析列表里的每个对端单独设置:

模式 行为 场景
Network Privacy Mode(默认) 只接受对端用 RPA 发来的包;如果对端用它的 Identity Address(真名)直接发,本机忽略 更强隐私,要求对端也守规矩用 RPA
Device Privacy Mode 既接受对端的 RPA,也接受对端用 Identity Address 发来的包 兼容那些绑定后就直接用固定地址的老设备

为什么需要 Device Privacy Mode? 有些从设备绑定后为了省事直接用 Static/Public 地址广播(不再用 RPA)。如果中心端是默认的 Network Privacy Mode,就会因为"你没用 RPA"而忽略它,导致连不上。这时把该对端设成 Device Privacy Mode 就能兼容。

对应命令:LE Set Privacy Mode

八、定向广播与 Privacy

定向广播(Directed Advertising,ADV_DIRECT_IND)里有 InitA(目标地址)字段。开启隐私后:

  • AdvA 用广播方自己的 RPA;
  • InitA目标设备的 RPA(广播方用存下的对端 IRK 生成)。

这样即使是"我在定向呼叫某台特定设备回连",空口里两个地址也都是 RPA,陌生人无法看出"谁在找谁"。这就是耳机能"悄悄"定向唤醒手机回连、又不泄露双方身份的原理。

九、Privacy 的演进

  • Privacy 1.0(BT 4.0/4.1):Host-based。RPA 生成/解析都在主机层,控制器不参与,每次广播都要把主机唤醒,功耗和实时性差,基本被淘汰。
  • Privacy 1.1 / LL Privacy(BT 4.2 起):Controller-based,引入解析列表,链路层自动解析。这是现在的主流。
  • BT 4.2 还新增了 Device/Network Privacy Mode,解决兼容性。

十、实战坑提醒

  1. 没存 IRK 却用了 RPA:对端解析不出你的地址,表现为"绑定过却每次都当陌生设备/连不上/反复配对"。绑定时务必分发并保存 IRK。
  2. 解析列表容量有限:控制器解析列表通常只有几个到几十个条目(芯片而异)。绑定设备多了会溢出,超出的对端解析不了。必要时做 LRU 淘汰或把解析放回 Host。
  3. 解析列表满时的坑:有些控制器在列表满后仍收到大量 RPA 广播会性能下降,甚至无法再添加新绑定。
  4. RPA Timeout 设置:默认 15 分钟。改太短会增加功耗;生产环境别设成 1 秒去"调试隐私"然后忘了改回来。
  5. Device vs Network Privacy Mode 选错:连不上老的、绑定后用固定地址的从设备时,优先检查是不是被 Network Privacy Mode 忽略了,改成 Device Privacy Mode 试试。
  6. Identity Address 泄露:Privacy 只保护空口地址;如果你的 GATT 里放了序列号、或广播 name 固定不变,照样能被追踪。隐私是"整体"的,不只是地址。
  7. Public 地址开隐私无意义的误区:设备如果本来就用 Public 地址且在 GAP 里公开身份,RPA 的意义有限;隐私要从产品设计层面统一考虑。
  8. 抓包时看到的是 RPA:用 nRF Sniffer 等抓包,广播地址是不断变化的 RPA,别以为是"抓到好多不同设备"。要跟踪一台开了隐私的设备,得让抓包工具也导入其 IRK 才能解析归并。
  9. iOS/Android 的地址随机化:现在手机默认都开 RPA(约每 15 分钟换)。做手机 App 扫描时,别用 MAC 地址做设备唯一标识——它会变;要用连接后的身份或业务层 ID。

十一、一句话总结

BLE Privacy 用"定时变化、只有持 IRK 者能解析"的 RPA 替代固定地址,从链路层对抗被动追踪;配对时分发 IRK、控制器用解析列表自动生成与还原地址,配合 RPA 超时和两种隐私模式,在隐私与兼容性之间取得平衡。 想在产品里真正做到隐私保护,除了开 RPA,还要注意别让 GATT 内容、固定广播名、业务 ID 成为新的"追踪指纹"。

更多 BLE / 鸿蒙星闪 / 芯片选型 / MCU 实战,持续更新