BLE 设备在广播和连接时,空口里会携带自己的设备地址。如果这个地址是固定不变的,任何人拿一部手机、开一个扫描 App,就能在商场、地铁、写字楼里长期追踪某个特定设备(进而追踪它的主人)。BLE Privacy(隐私特性)就是为了对抗这种"地址追踪"而生的一整套机制:让设备对外使用一个会定时变化、且只有"认识它的人"才能还原真身的地址——RPA(Resolvable Private Address,可解析私有地址)。
这篇文章把 Privacy 从"为什么需要"到"控制器怎么实现"讲清楚,包括 IRK、解析列表(Resolving List)、两种隐私模式、RPA 超时、以及一堆实战里会踩的坑。
先理解威胁模型。一个 BLE 设备(比如智能手环、耳机、手机)在未连接时会周期性发广播包,广播包里带 AdvA(广播者地址)。如果 AdvA 是一个固定的 Public 地址或 Static Random 地址:
AA:BB:CC:11:22:33这就是被动追踪(passive tracking)。它不需要连接、不需要配对,只要静静地扫描广播即可。早年很多可穿戴设备、iBeacon、甚至手机都因为固定 MAC 被用于商场客流分析和轨迹追踪。
Privacy 的核心思路:对外暴露的地址要经常换,而且换了之后,陌生人看不出"新地址"和"旧地址"是同一台设备,但已经和它绑定过的对端(存了它的 IRK)依然能认出来。
BLE 地址分两大类(详见《BLE 设备地址 BD_ADDR 科普》),这里只聚焦隐私相关的:
| 地址类型 | 高 2 bit | 是否变化 | 隐私性 |
|---|---|---|---|
| Public | — | 不变 | 无(可被长期追踪) |
| Static Random | 11 |
上电周期内不变 | 弱(一次开机内可追踪) |
| Non-Resolvable Private (NRPA) | 00 |
定时变 | 强,但对端也认不出(少用) |
| Resolvable Private (RPA) | 10 |
定时变 | 强,且对端可解析 ← Privacy 主角 |
RPA 就是 Privacy 机制产生的地址:对陌生人是随机噪声,对"老朋友"可还原。
RPA 是一个 48 位地址,由两部分组成:
| 47 24 | 23 0 |
| hash | prand |
| (24 bit) | (24 bit) |
10(标识这是 RPA)。剩下 22 位是真随机。hash = ah(IRK, prand)
其中 ah 是蓝牙规范定义的一个基于 AES-128 的哈希函数(本质是 AES-128(IRK, padding||prand) 取低 24 位)。
关键点:
- 只有持有该设备 IRK(Identity Resolving Key,身份解析密钥) 的人,才能用同样的 ah 重新算一遍,验证 hash 是否匹配,从而确认"这个变化的 RPA 就是我认识的那台设备"。
- 每次换地址,prand 变 → hash 跟着变 → 整个 48 位地址全变,陌生人看不出关联。
// 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 后,对端遍历自己解析列表里存的每个 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 是 Privacy 的核心密钥,它决定了"谁能认出我"。
(IRK, Identity Address) 发给对端;对端存进绑定库/解析列表。所以"手机地址天天变,但耳机还能秒回连"的原因就是:耳机绑定时存了手机的 IRK,每次都能把手机变化的 RPA 解析回它的真身。
特殊:IRK 全 0 是合法的"约定",表示"我不用 RPA,请用我的 Identity Address 认我"。
RPA 的生成和解析可以放在 Host(主机层,软件) 做,也可以放在 Controller(控制器,芯片底层) 做。现代方案几乎都用 Controller-based Privacy(LL Privacy,链路层隐私),因为:
控制器里维护一张 Resolving List(解析列表),每个条目包含:
{
Peer Identity Address (对端真名) + Address Type,
Peer IRK (解析对端 RPA 用),
Local IRK (生成本机 RPA 用)
}
对应的 HCI 命令(主机配置控制器):
LE Add Device To Resolving ListLE Remove Device From Resolving ListLE Clear Resolving ListLE Set Address Resolution Enable(总开关)LE Set Resolvable Private Address Timeout(设置 RPA 超时)启用后,控制器:
- 收包时:自动把对端 RPA 解析成 Identity Address 再上报给 Host(Host 看到的是稳定真名,不用管地址在变);
- 发包时:自动用 Local IRK 生成本机 RPA 填进 AdvA/InitA。
RPA 不是每个包都换,而是每隔一段时间换一次,由 RPA Timeout 控制:
坑:RPA 只在下一次广播/扫描/发起连接开始时才会用上新值,不是到点立刻在空口生效。已经在进行的连接不会因为超时而换地址。
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。
定向广播(Directed Advertising,ADV_DIRECT_IND)里有 InitA(目标地址)字段。开启隐私后:
AdvA 用广播方自己的 RPA;InitA 用目标设备的 RPA(广播方用存下的对端 IRK 生成)。这样即使是"我在定向呼叫某台特定设备回连",空口里两个地址也都是 RPA,陌生人无法看出"谁在找谁"。这就是耳机能"悄悄"定向唤醒手机回连、又不泄露双方身份的原理。
BLE Privacy 用"定时变化、只有持 IRK 者能解析"的 RPA 替代固定地址,从链路层对抗被动追踪;配对时分发 IRK、控制器用解析列表自动生成与还原地址,配合 RPA 超时和两种隐私模式,在隐私与兼容性之间取得平衡。 想在产品里真正做到隐私保护,除了开 RPA,还要注意别让 GATT 内容、固定广播名、业务 ID 成为新的"追踪指纹"。