ESP32 Arduino Core BLE 配对与安全实现完全指南:IO 能力、配对方法与 Bluedroid/NimBLE 双栈实践
【免费下载链接】arduino-esp32Arduino core for the ESP32 family of SoCs项目地址: https://gitcode.com/GitHub_Trending/ar/arduino-esp32
本篇技术指南以 libraries/BLE/README.md 为主体,系统讲解 ESP32 Arduino Core 中 BLE(Bluetooth Low Energy)配对(Pairing)与安全(Security)的完整实现:从 Pairing/Bonding 基础概念、IO 能力(IO Capability)与配对方法的匹配关系,到 Bluedroid(ESP32)与 NimBLE(其他 SoC)两套蓝牙协议栈在特性(Properties)与权限(Permissions)上的差异,最后给出可直接落地的代码示例与故障排查方案。读完本文,你将能够为自己的 ESP32 设备正确选择安全等级、配置静态/动态 Passkey、编写跨协议栈兼容的加密特征值,并排查"始终走 Just Works""安全特征读取失败"等高频问题。
BLE 安全核心概念:配对、绑定与安全等级
在动手写代码之前,需要先厘清三组基础概念,它们是理解整个 BLE 安全体系的地基。
Pairing 与 Bonding
- Pairing(配对):两台设备之间建立加密密钥的过程。配对完成后,链路即被加密。
- Bonding(绑定):将配对生成的密钥持久化存储,供后续重连时直接复用,实现"永久配对"。绑定数据默认保存在 NVS 中,这也是开发调试时"配过一次、重启后仍认为已配对"的原因。
Legacy Pairing 与 Secure Connections
- Legacy Pairing:蓝牙 4.0/4.1 时代的原始配对方式,使用较弱的密码学算法(如 Short Term Key 派生)。
- Secure Connections(安全连接):蓝牙 4.2+ 引入的增强配对,使用基于 FIPS 认可算法的椭圆曲线 Diffie-Hellman(ECDH)进行密钥协商,抗窃听能力显著增强。
安全等级
- Just Works:只提供加密、不提供用户验证的配对方式。对被动窃听(passive eavesdropping)敏感。
- MITM Protected:通过用户参与验证(如输入 PIN、核对数字)防止中间人攻击。
这三组概念直接决定后续ESP_LE_AUTH_*认证模式与ESP_IO_CAP_*IO 能力的选择,是整个安全配置的输入参数。
IO 能力(IO Capability)详解
配对过程中,协议栈根据两端设备的 IO 能力自动选择可行的配对方法。ESP32 Arduino BLE 库在 BLESecurity.h 中定义了五档 IO 能力,且在 NimBLE 编译环境下通过宏映射到 NimBLE 自身的BLE_HS_IO_*常量,保证两端 API 一致:
| 能力 | 库常量 | 可显示 | 可输入 | 可确认 | 典型设备 |
|---|---|---|---|---|---|
| 无输入无输出 | ESP_IO_CAP_NONE | ❌ | ❌ | ❌ | 传感器节点、Beacon、简单执行器 |
| 仅显示 | ESP_IO_CAP_OUT | ✅ | ❌ | ❌ | 电子墨水屏、LED 矩阵屏 |
| 仅键盘 | ESP_IO_CAP_IN | ❌ | ✅ | ❌ | 纯按键设备、旋转编码器 |
| 显示+确认 | ESP_IO_CAP_IO | ✅ | ❌ | ✅ | 带显示屏和确认按钮的设备 |
| 键盘+显示 | ESP_IO_CAP_KBDISP | ✅ | ✅ | ✅ | 带完整 UI 的 ESP32 设备 |
从源码可见,BLESecurity构造函数的默认 IO 能力为ESP_IO_CAP_NONE(见 BLESecurity.cpp),即"默认只支持 Just Works"。这也是很多开发者没有显式配置能力时,配对永远走 Just Works 的根因之一。
配对方法(Pairing Methods)详解
Just Works
- 安全:仅加密,无 MITM 保护
- 体验:全自动,无需任何用户交互
- 适用:安全性要求不高、追求便利的场景(运动手环、鼠标)
- 弱点:配对期间易受被动窃听
Passkey Entry
- 安全:完整 MITM 保护
- 体验:一方设备显示 6 位数字(000000–999999),另一方由用户输入
- 适用:键盘连接电脑等"一端显示、一端输入"的场景
- 流程:显示方随机生成 6 位数字 → 输入方用户键入 → 双方数字一致则配对成功
需要特别强调:静态 Passkey 并不能绕过 MITM。即使你固定了一个 Passkey,也必须把 IO 能力设置为支持 MITM 的值(如ESP_IO_CAP_KBDISP),否则协议栈会退化为 Just Works。这一点在官方示例 Server_secure_static_passkey.ino 的注释中有明确说明。
Numeric Comparison(仅 Secure Connections)
- 安全:完整 MITM 保护
- 体验:两台设备显示相同的 6 位数字,用户核对后双方各自确认
- 适用:两台智能手机/平板之间的配对
- 流程:双方显示同一数字 → 用户核对一致 → 两台设备均确认"Yes"
Out-of-Band(OOB)
- 安全:最高安全等级
- 体验:通过外部信道(NFC、二维码等)交换配对信息
- 注意:本库不支持 OOB。当 OOB 数据可用时协议栈会优先使用它,但由于本库未实现该通道,实际不会触发。
配对方法兼容矩阵
配对时,**发起方(Initiator,通常是 Client)与响应方(Responder,通常是 Server)**的 IO 能力组合决定了最终可用的配对方法。矩阵逻辑概括如下:
- 双方任一端为
ESP_IO_CAP_NONE→ 只能 Just Works(无法 MITM) - 一端"仅显示"、一端"仅键盘" → Passkey Entry
- 双方"显示+确认"或更高能力 → 可 Numeric Comparison(Secure Connections 下)
ESP_IO_CAP_KBDISP组合 → 全部配对方法可用
这一矩阵解释了后文所有实战场景的结果走向。
Bluedroid 与 NimBLE:两套协议栈的关键差异
ESP32 Arduino Core 在不同 SoC 上使用不同的蓝牙协议栈,这是本库安全 API 设计中最容易踩坑的地方。核心事实如下:
Bluedroid(默认用于 ESP32)
- ESP-IDF 的默认蓝牙协议栈,同时支持经典蓝牙(Bluetooth Classic)与 BLE。
- 相比 NimBLE 占用更多 Flash 与 RAM。
- 特征值(Characteristic)与描述符(Descriptor)的访问权限通过
setAccessPermissions()单独设置。 - README 明确声明:Arduino Core v4.0.0 中将用 NimBLE 替换 Bluedroid,经典蓝牙与 Bluedroid 不再支持(但可通过将 Arduino 作为 ESP-IDF 组件继续使用)。
- 其原始上游项目 esp32-snippets 已不再维护。
NimBLE(默认用于 ESP32 之外的其他 SoC)
- 轻量级协议栈,仅支持 BLE。
- 占用 Flash 与 RAM 更少。
- 特征值的访问权限使用创建时传入的专用属性位表达(如
PROPERTY_READ_AUTHEN);描述符权限仍通过setAccessPermissions()设置。 - 部分实现基于 h2zero 的 NimBLE-Arduino 工作。
为什么会产生"属性被忽略"的怪现象
从 BLECharacteristic.h 的源码可以精确解释跨栈兼容问题:
- Bluedroid 编译环境下,
PROPERTY_READ_ENC、PROPERTY_READ_AUTHEN、PROPERTY_READ_AUTHOR、PROPERTY_WRITE_ENC、PROPERTY_WRITE_AUTHEN、PROPERTY_WRITE_AUTHOR全部被定义为0,注释明确写着"Not supported by Bluedroid. Use setAccessPermissions() instead." - NimBLE 编译环境下,这些属性对应真实的 GATT 特征标志
BLE_GATT_CHR_F_*。
反过来,setAccessPermissions()的实现(见 BLECharacteristic.cpp)被#ifdef CONFIG_BLUEDROID_ENABLED包裹,NimBLE 下该调用是空操作。
因此,跨栈可移植代码必须"双管齐下":既在 properties 里加 NimBLE 的认证位,又调用setAccessPermissions()设置 Bluedroid 的权限位。运行时可用BLEDevice::getBLEStackString()(定义于 BLEDevice.h)确认当前编译的是哪套栈。
五大常见实战场景
将 IO 能力矩阵应用到真实产品形态,可归纳出以下高频组合:
场景 1:手机 App ↔ ESP32 传感器节点
- 设备:手机(
ESP_IO_CAP_IO)↔ 传感器(ESP_IO_CAP_NONE) - MITM:不可达(一端为 NONE,退化为 Just Works)
- 特征认证:仅 Bonding
- 结果:Just Works + 绑定以支持重连
- 适用:气象站、环境监测设备
场景 2:ESP32 智能锁 ↔ 手机 App
- 设备:锁(
ESP_IO_CAP_OUT)↔ 手机(ESP_IO_CAP_KBDISP) - MITM:必须启用(安全门禁)
- 特征认证:Bonding + Secure Connection + MITM
- 结果:Passkey Entry(ESP32 显示、手机输入)
- 实现:静态 Passkey 或动态显示
场景 3:ESP32 配置设备 ↔ 管理工具
- 设备:ESP32(
ESP_IO_CAP_KBDISP)↔ 管理工具(ESP_IO_CAP_KBDISP) - MITM:必须启用
- 特征认证:Bonding + Secure Connection + MITM
- 结果:Legacy 下走 Passkey Entry;Secure Connections 下走 Numeric Comparison
- 适用:工业 IoT 配置、网络设置
场景 4:ESP32 Beacon ↔ 扫码 App
- 设备:Beacon(
ESP_IO_CAP_NONE)↔ 扫码器(ESP_IO_CAP_IO) - MITM:不需要(仅广播)
- 特征认证:无
- 结果:无需配对
- 适用:资产追踪、近场感知
场景 5:ESP32 智能家居中枢 ↔ 多设备
- 设备:中枢(
ESP_IO_CAP_IO)↔ 各类传感器(ESP_IO_CAP_NONE) - MITM:任一端为 NONE 时不可能实现
- 特征认证:仅 Bonding
- 结果:仅 Just Works
- 适用:集中式家庭自动化控制器
这些场景的代码级参考可查看库内 secure 示例:Server_secure_static_passkey.ino、Client_secure_static_passkey.ino 与 Server_secure_authorization.ino。
实现指南:从 IO 能力到安全配置
选择 IO 能力
#include <BLESecurity.h> // 保守方案——限制配对方法,但保证兼容性 pSecurity->setCapability(ESP_IO_CAP_NONE); // 仅 Just Works // 均衡方案——良好的体验与可选的安全 pSecurity->setCapability(ESP_IO_CAP_IO); // Just Works 或 Numeric Comparison // 最高安全——支持所有配对方法 pSecurity->setCapability(ESP_IO_CAP_KBDISP); // 所有配对方法可用配置认证模式
BLESecurity *pSecurity = new BLESecurity(); // 低安全应用(传感器、环境监测) pSecurity->setAuthenticationMode(ESP_LE_AUTH_NO_BOND); // 标准安全 + 绑定(智能家居设备) pSecurity->setAuthenticationMode(ESP_LE_AUTH_BOND); // 需要 MITM 保护(门禁、支付) pSecurity->setAuthenticationMode(ESP_LE_AUTH_REQ_MITM | ESP_LE_AUTH_BOND); // 最高安全:Secure Connections + MITM + 绑定(关键系统) pSecurity->setAuthenticationMode(ESP_LE_AUTH_REQ_SC_MITM_BOND); // 等价的可读性写法(bonding, mitm, sc 三个布尔参数) pSecurity->setAuthenticationMode(true, true, true);源码层面,setAuthenticationMode(bool, bool, bool)在 Bluedroid 下会同时设置ESP_BLE_SM_AUTHEN_REQ_MODE并根据sc/mitm组合选择ESP_BLE_SEC_ENCRYPT_MITM或ESP_BLE_SEC_ENCRYPT_NO_MITM加密级别;在 NimBLE 下则直接写入ble_hs_cfg.sm_bonding、sm_mitm、sm_sc(见 BLESecurity.cpp)。
静态 Passkey 示例
// 设置静态 passkey 以获得一致的配对体验 #define DEVICE_PASSKEY 123456 pSecurity->setPassKey(true, DEVICE_PASSKEY); // static=true, passkey=123456 pSecurity->setCapability(ESP_IO_CAP_KBDISP); // 即使使用静态 passkey 也需要支持 MITM 的能力注意setPassKey()的完整签名是setPassKey(bool staticPasskey = false, uint32_t passkey = BLE_SM_DEFAULT_PASSKEY),其中BLE_SM_DEFAULT_PASSKEY定义为123456(见 BLESecurity.h)。当使用默认 Passkey 时,源码会打印两条警告日志(见 BLESecurity.cpp):
*WARNING* Using default passkey: 123456 *WARNING* Please use a random passkey or set a different static passkey生产环境务必更换。
动态 Passkey 与每次连接重新生成
库还提供了随机 Passkey 相关能力:
pSecurity->setPassKey(false); // 随机 passkey(0–999999 之间生成) pSecurity->regenPassKeyOnConnect(true); // 每次新连接重新生成随机 passkey uint32_t pk = pSecurity->getPassKey(); // 获取当前使用的 passkey实现位于 BLESecurity.cpp:generateRandomPassKey()调用random(0, 999999);regenPassKeyOnConnect(true)时,getPassKey()会在每次连接前重新生成,适合"每次配对使用新 PIN"的高安全需求。
特征值安全:属性与权限完整参考
Bluedroid:属性(Properties)+ 权限(Permissions)双层模型
支持的属性:
BLECharacteristic::PROPERTY_READ // 读操作 BLECharacteristic::PROPERTY_WRITE // 写操作 BLECharacteristic::PROPERTY_WRITE_NR // 无响应写 BLECharacteristic::PROPERTY_NOTIFY // 通知 BLECharacteristic::PROPERTY_INDICATE // 指示 BLECharacteristic::PROPERTY_BROADCAST // 广播特征值与描述符的访问权限:
// 基础权限 ESP_GATT_PERM_READ // 允许读 ESP_GATT_PERM_WRITE // 允许写 // 需要加密 ESP_GATT_PERM_READ_ENCRYPTED // 读需加密 ESP_GATT_PERM_WRITE_ENCRYPTED // 写需加密 // 需要认证(MITM 保护) ESP_GATT_PERM_READ_ENC_MITM // 读需加密 + MITM ESP_GATT_PERM_WRITE_ENC_MITM // 写需加密 + MITM // 需要授权(触发授权回调) ESP_GATT_PERM_READ_AUTHORIZATION // 读需授权回调 ESP_GATT_PERM_WRITE_AUTHORIZATION // 写需授权回调NimBLE:属性即权限模型
支持的属性(含 NimBLE 专属安全位):
// 基础属性 BLECharacteristic::PROPERTY_READ // 读操作 BLECharacteristic::PROPERTY_WRITE // 写操作 BLECharacteristic::PROPERTY_WRITE_NR // 无响应写 BLECharacteristic::PROPERTY_NOTIFY // 通知 BLECharacteristic::PROPERTY_INDICATE // 指示 BLECharacteristic::PROPERTY_BROADCAST // 广播 // NimBLE 专属属性 // 需要加密 BLECharacteristic::PROPERTY_READ_ENC // 读需加密 BLECharacteristic::PROPERTY_WRITE_ENC // 写需加密 // 需要认证(MITM 保护) BLECharacteristic::PROPERTY_READ_AUTHEN // 读需加密 + MITM BLECharacteristic::PROPERTY_WRITE_AUTHEN // 写需加密 + MITM // 需要授权 BLECharacteristic::PROPERTY_READ_AUTHOR // 读需授权回调 BLECharacteristic::PROPERTY_WRITE_AUTHOR // 写需授权回调描述符访问权限(与 Bluedroid 使用同一套ESP_GATT_PERM_*常量,含义相同)。
按安全等级分层的用法示例
无安全(两栈通用):
uint32_t properties = BLECharacteristic::PROPERTY_READ | BLECharacteristic::PROPERTY_WRITE;仅加密:
// NimBLE uint32_t properties = BLECharacteristic::PROPERTY_READ | BLECharacteristic::PROPERTY_WRITE | BLECharacteristic::PROPERTY_READ_ENC | BLECharacteristic::PROPERTY_WRITE_ENC; // Bluedroid uint32_t properties = BLECharacteristic::PROPERTY_READ | BLECharacteristic::PROPERTY_WRITE; pChar->setAccessPermissions(ESP_GATT_PERM_READ_ENCRYPTED | ESP_GATT_PERM_WRITE_ENCRYPTED);MITM 保护(认证):
// NimBLE uint32_t properties = BLECharacteristic::PROPERTY_READ | BLECharacteristic::PROPERTY_WRITE | BLECharacteristic::PROPERTY_READ_AUTHEN | BLECharacteristic::PROPERTY_WRITE_AUTHEN; // Bluedroid uint32_t properties = BLECharacteristic::PROPERTY_READ | BLECharacteristic::PROPERTY_WRITE; pChar->setAccessPermissions(ESP_GATT_PERM_READ_ENC_MITM | ESP_GATT_PERM_WRITE_ENC_MITM);需要授权(应用层二次校验):
// NimBLE uint32_t properties = BLECharacteristic::PROPERTY_READ | BLECharacteristic::PROPERTY_WRITE | BLECharacteristic::PROPERTY_READ_AUTHOR | BLECharacteristic::PROPERTY_WRITE_AUTHOR; // Bluedroid uint32_t properties = BLECharacteristic::PROPERTY_READ | BLECharacteristic::PROPERTY_WRITE; pChar->setAccessPermissions(ESP_GATT_PERM_READ_AUTHORIZATION | ESP_GATT_PERM_WRITE_AUTHORIZATION);授权模式下,需要实现BLESecurityCallbacks::onAuthorizationRequest(connHandle, attrHandle, isRead),返回true表示放行、false表示拒绝。注意该回调的默认实现会接受一切请求并打印警告(见 BLESecurity.cpp),生产环境必须重写。
安全考量:何时需要 MITM
按应用类型划分
- 始终需要 MITM:支付系统、医疗设备、门禁控制
- 通常需要:文件传输、个人数据同步、键盘
- 可选:运动手环、环境传感器、鼠标
- 绝不需要:Beacon、纯广播设备
Legacy 与 Secure Connections 的选择
- Legacy:兼容 2010 年以来的所有 BLE 设备
- Secure Connections:安全性更强,但要求双方支持蓝牙 4.2+(2014 年后)
- 建议:两者都支持,可用时优先 Secure Connections
已知弱点
- Just Works:初始配对易被被动窃听
- Legacy Pairing:使用较弱的密码学算法
- Passkey 暴力破解:6 位 Passkey 仅 100 万种组合
- 物理安全:显示的 Passkey 可能被肩窥(shoulder-surfing)
故障排查手册
配对始终走 Just Works
// ❌ 问题:缺少 MITM 标志 pSecurity->setAuthenticationMode(ESP_LE_AUTH_REQ_SC_BOND); // ✅ 解决:加上 MITM 保护 pSecurity->setAuthenticationMode(ESP_LE_AUTH_REQ_SC_MITM_BOND);静态 Passkey 不被请求 / 读取安全特征无反应
// ❌ 问题:IO 能力不支持 MITM pSecurity->setCapability(ESP_IO_CAP_NONE); // 无法支撑 MITM // ✅ 解决:即使使用静态 passkey 也要设置正确的能力 pSecurity->setCapability(ESP_IO_CAP_KBDISP); // MITM 必需 pSecurity->setPassKey(true, 123456);安全特征访问失败(跨栈方法用错)
// ❌ 问题:只用了 Bluedroid 的方法(在 NimBLE 上无效) uint32_t properties = BLECharacteristic::PROPERTY_READ; pCharacteristic = pService->createCharacteristic(uuid, properties); pCharacteristic->setAccessPermissions(ESP_GATT_PERM_READ_ENC_MITM); // NimBLE 下被忽略! // ✅ 解决:两种方法同时使用,实现跨栈兼容 uint32_t properties = BLECharacteristic::PROPERTY_READ | BLECharacteristic::PROPERTY_READ_AUTHEN; // 供 NimBLE pCharacteristic = pService->createCharacteristic(uuid, properties); pCharacteristic->setAccessPermissions(ESP_GATT_PERM_READ_ENC_MITM); // 供 Bluedroid配对一次成功后再次失败(NVS 缓存问题)
开发调试期间,旧的绑定数据会干扰新的安全测试:
// ✅ 解决:测试阶段清空 NVS 配对数据 Serial.println("Clearing NVS pairing data for testing..."); nvs_flash_erase(); nvs_flash_init();⚠️ 注意:nvs_flash_erase()会清空整个 NVS,包括蓝牙身份密钥(IR/IRK),导致每次开机 IRK 都变化。官方示例 Server_secure_static_passkey.ino 对此有明确说明:生产环境若需要稳定的 IRK(如 Home Assistant 存在检测),应移除这两行;只清绑定数据而不动身份密钥,应改用esp_ble_remove_bond_device()(Bluedroid)或ble_store_util_delete_all()(NimBLE)。
默认 Passkey 警告
日志中出现以下内容即表示使用了默认 Passkey:
*WARNING* Using default passkey: 123456 *WARNING* Please use a random passkey or set a different static passkey// ✅ 解决:更换默认值 #define CUSTOM_PASSKEY 567890 // 你的专属 passkey pSecurity->setPassKey(true, CUSTOM_PASSKEY);配对过程中连接断开
实现安全回调,获得更完善的错误处理与日志:
class MySecurityCallbacks : public BLESecurityCallbacks { void onAuthenticationComplete(esp_ble_auth_cmpl_t param) override { if (param.success) { Serial.println("Pairing successful!"); } else { Serial.printf("Pairing failed, reason: %d\n", param.fail_reason); } } }; BLEDevice::setSecurityCallbacks(new MySecurityCallbacks());完整回调体系(定义于 BLESecurity.h)还包括:
onPassKeyRequest():有输入能力的一方请求 Passkey(默认返回123456,不安全,必须重写)onPassKeyNotify(pass_key):有显示能力的一方展示需要对方输入的 PasskeyonSecurityRequest():对端请求安全连接时返回是否接受(默认接受一切)onConfirmPIN(pin):双方均为显示+确认能力时核对 PIN(默认接受一切,必须重写)onAuthorizationRequest(connHandle, attrHandle, isRead):授权请求处理(默认放行,必须重写)
跨平台最佳实践模板
// 始终同时使用两种方法以获得最大兼容性 uint32_t secure_properties = BLECharacteristic::PROPERTY_READ | BLECharacteristic::PROPERTY_WRITE | BLECharacteristic::PROPERTY_READ_AUTHEN | // NimBLE BLECharacteristic::PROPERTY_WRITE_AUTHEN; // NimBLE BLECharacteristic *pChar = pService->createCharacteristic(uuid, secure_properties); // Bluedroid 权限(NimBLE 下忽略,但无副作用) pChar->setAccessPermissions(ESP_GATT_PERM_READ_ENC_MITM | ESP_GATT_PERM_WRITE_ENC_MITM);调试技巧与进阶能力
调试要点
- 记录配对特性交换:观察两端协商的能力与密钥分发标志
- 监控协议栈选定的配对方法:确认实际走的是 Just Works 还是 Passkey Entry
- 检查用户输入方法的超时值:Passkey/Numeric Comparison 均有超时限制
- 核对两端的密钥分发标志:
ESP_BLE_ENC_KEY_MASK(加密密钥)与ESP_BLE_ID_KEY_MASK(身份密钥)默认同时分发,需保证两端一致
运行时识别协议栈
String stackType = BLEDevice::getBLEStackString(); Serial.println("Using BLE stack: " + stackType);该 API 返回当前编译配置下实际启用的协议栈(BLEDevice.h中定义BLEStack枚举:BLUEDROID/NIMBLE/UNKNOWN),可用于日志输出或条件编译决策。
进阶:绑定后获取 IRK(身份解析密钥)
官方安全示例还演示了绑定成功后检索本地与对端 IRK 的能力(Server_secure_static_passkey.ino、Client_secure_static_passkey.ino):
// 本地 IRK,多种格式输出 String irkString = BLEDevice::getLocalIRKString(); // 逗号分隔十六进制 String irkBase64 = BLEDevice::getLocalIRKBase64(); // Base64(Home Assistant Private BLE Device) String irkReverse = BLEDevice::getLocalIRKReverse(); // 反序十六进制(Home Assistant ESPresense) // 对端 IRK(需传入对端地址,绑定时获取) uint8_t irk[16]; BLEDevice::getPeerIRK(peerAddr, irk);⚠️ 安全警告:IRK 是设备的长期标识符,任何持有 IRK 的人都可在 BLE 存在检测系统中跟踪或冒充该设备,务必妥善保管。
认证时序的进阶控制
源码还提供了两个可用于编排时序的 API(见 BLESecurity.h):
setForceAuthentication(bool):默认true,连接建立后立即启动认证(与服务发现并发);设为false时,认证延迟到首次访问受保护特征时才触发(先发现、再读取、后认证重试),事件顺序更可预测。源码注释显示 v4.0.0 计划将默认值改为false。waitForAuthenticationComplete(timeoutMs):Bluedroid 下通过 FreeRTOS 信号量阻塞等待认证完成,防止绑定开启时 GATT 操作早于配对完成执行。
标准参考
- Bluetooth Core Specification v5.4:Volume 3, Part H(Security Manager)
- Bluetooth Assigned Numbers:IO Capability 取值定义
- FIPS-140-2:Secure Connections 采用的密码学标准
结语
BLE 安全配置的正确性取决于三件事:认证模式(ESP_LE_AUTH_*)、IO 能力(ESP_IO_CAP_*)与特征安全属性/权限(Properties/Permissions)三者的一致性。本文结合 libraries/BLE/README.md 的完整参考与 BLESecurity.cpp、BLECharacteristic.h 等源码实现,给出了从概念到代码、从单栈到跨栈的完整路线。动手实践时,建议以库内 examples 目录下的Server_secure_static_passkey、Client_secure_static_passkey、Server_secure_authorization三个安全示例为起点,再按本文的故障排查清单逐项验证。
【免费下载链接】arduino-esp32Arduino core for the ESP32 family of SoCs项目地址: https://gitcode.com/GitHub_Trending/ar/arduino-esp32
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考