ESP-IDF BluFi 完整指南:把 Wi-Fi 密码安全送进无屏设备的蓝牙配网全流程
【免费下载链接】esp-idfEspressif IoT Development Framework. Official development framework for Espressif SoCs.项目地址: https://gitcode.com/GitHub_Trending/es/esp-idf
一块没有屏幕、没有按键的 ESP32,Wi-Fi 密码要从哪里进去?ESP-IDF 的 BluFi 特性给出了答案:它让设备通过低功耗蓝牙(BLE)自建一条加密通道,手机的 App 把 SSID 和密码从这条通道送进来。本文按数据流动的顺序,带你跟完整个配网过程,再拆到帧和密钥这一层。
这个特性解决什么问题
没有屏幕之前,常见做法各有死角:
- 串口 CLI:能改配置,但产线上每块板子都要接电脑,批量部署不现实。
- 设备开 SoftAP 让手机连:设备必须先开热点,占用 Wi-Fi 模式;而且这条链路本身不加密,谁都能接进来改配置。
- 广播式配网(ESP-Touch 一类):密码以明文广播在局域网里,安全性弱。
BluFi 的做法是反过来的:设备保持正常的 Wi-Fi 模式(默认 Station),只把 BLE 拉起来当"临时邮差"。手机装一个支持 BluFi 协议的 App(乐鑫官方提供 EspBlufi,Android/iOS 均可用),连上设备后,SSID、密码在 BLE 上以对称加密的方式逐帧传输。配完网,这条链路随时可以断开,Wi-Fi 全程不受影响。
一句话:以前的方案要么"人围着设备转",要么"链路裸奔";BluFi 让设备自己站在原地,密码走一条一次一密的加密管道。
跟着一份配置走完全程
以最常见的 Station 配网为例,一条 SSID + 密码在系统里经历六步:
- 广播:设备上电后初始化 Wi-Fi、NVS,然后
esp_blufi_adv_start()开始 BLE 广播,广播数据里带着 BluFi 的 GATT 服务 UUID0xFFFF,相当于举着"我会配网"的牌子。串口此时打印BLUFI init finish。 - 连接:手机 App 作为 GATT Client 扫到广播后连上来,拿到两个特征值——
0xFF01可写(手机→设备)、0xFF02可读可通知(设备→手机)。此后所有 BluFi 帧都从这两个特征值进出。串口打印BLUFI ble connect。 - 协商密钥:手机先分片发送 DH 参数(P、G 以及手机自己的公钥)。设备侧用 RFC 7919 的 3072 位 DH 算出共享密钥,再做 SHA-256 得到 256 位 AES 密钥,并用域分离前缀分别推导出加密/解密两把 IV。
- 切换安全模式:手机发一帧控制帧声明安全模式(高 4 位管控制帧、低 4 位管数据帧,
0011表示"校验 + 加密"全开)。从此刻起,数据帧开始加密。 - 传输配置:SSID 和密码各自作为独立数据帧发送,随后一帧控制帧 0x3(Connect to AP)收尾,告诉设备"信息齐了,可以连"。设备回调里
ESP_BLUFI_EVENT_RECV_STA_SSID、ESP_BLUFI_EVENT_RECV_STA_PASSWD依次触发,最后esp_wifi_connect()执行连接。 - 状态回传:拿到 IP 后,设备把结果打包成一帧"Wi-Fi 连接状态报告"(subtype
0xf)经0xFF02通知回手机,内容包含 opmode、连接状态、BSSID、SSID。失败的话,报告里带断连原因码和 RSSI,App 能直接显示"密码错误"还是"信号太弱"。
全程每一帧都带自增序列号参与校验计算,防重放;超过单帧上限的大数据(比如 Wi-Fi 扫描列表)自动分片。
三分钟跑通:准备清单与分步操作
🛠️准备清单
- 硬件:ESP32 / C2 / C3 / C5 / C6 / C61 / S3 / S31 开发板一块,USB 线(供电 + 串口)
- 软件:examples/bluetooth/blufi/ 示例工程;手机上装 EspBlufi App(示例的 README.md 里有下载入口)
- 权限:手机授予蓝牙权限,Android 还需位置权限(BLE 扫描的硬性要求)
分步操作(每步都给你可自查的预期现象):
- 烧录:
idf.py -p PORT flash monitor。 预期:串口出现BLUFI VERSION 0102和BLUFI init finish两行。没有第二行就不要往下走,说明 BLE 侧没起来。 - 连接:打开 EspBlufi,下拉刷新,点击设备名(默认
BLUFI_DEVICE)→ Connect。 预期:App 显示连接成功;串口出现BLUFI ble connect。设备此时会自动停止广播,省得别的设备抢进来。 - 配 Station:点 Networking → 模式选 Station → 刷新选择目标 SSID → 输密码 → Confirm。 预期:App 弹出连接结果,红框区域显示模式、BSSID、SSID 和状态;串口能看到
Recv STA SSID和Recv STA PASSWORD(注意密码是明文打印的,见下文)。 - 配 SoftAP:同样入口,模式选 SoftAP,填 SSID、密码、加密方式、信道、最大连接数 → Confirm。 预期:手机 Wi-Fi 列表里立刻出现你刚起的热点;设备串口打印
station ... join。
拆开看内部:三个值得看的实现要点
1. 帧结构:固定 5 字节头 + 变长数据 + 2 字节尾
每帧的头部是Type(1) + Frame Control(1) + Sequence(1) + Data Length(1),尾部是 2 字节 CRC16 校验,覆盖范围是"序列号 + 长度 + 明文数据"。Frame Control 五个标志位各管一件事:0x01 是否加密、0x02 是否带校验、0x04 方向、0x08 是否需要 ACK、0x10 是否分片。序列号每发一帧 +1,断线重连后清零。把序列号卷进校验和,是整条链路防重放的核心手段——重放帧过不了 CRC。
2. 分片:接收方先知道"总共多大"
设了分片位(0x10)的帧,数据区前两字节先给出剩余内容的总长度,本帧只装Data Length - 2字节的实际内容。接收方据此一次性分配内存,边收边拼。为什么这么设计?因为 BLE 单帧 MTU 小,Wi-Fi 扫描列表动辄几百字节,不预知总长就只能反复扩容。
3. 可插拔的安全回调:协议骨架与密码学分离
协议层只管拆帧、校验、分片重组,加密细节全部甩给应用层注册的四个回调:
static esp_blufi_callbacks_t example_callbacks = { .negotiate_data_handler = blufi_dh_negotiate_data_handler, .encrypt_func = blufi_aes_encrypt, .decrypt_func = blufi_aes_decrypt, .checksum_func = blufi_crc_checksum, }; esp_blufi_host_and_cb_init(&example_callbacks);示例的默认实现是 3072 位 DH + AES-CTR + CRC16。这里有个硬约束:加解密必须原地进行、前后等长,因为协议里不预留长度变化。另一个隐藏成本:没有硬件大数乘法(MPI)的芯片上,3072 位模幂纯软件跑约 12 秒,所以示例在开始广播前就后台预生成 DH 密钥对,把耗时挪到关键路径之外(见 examples/bluetooth/blufi/main/blufi_security.c)。换掉回调,你也能塞 RSA/ECC 或自己的算法——这也是官方提醒"默认实现仅供演示"的原因。
高频问题与排障
🔍 按"现象 → 原因 → 处理"来查:
现象:App 列表里找不到设备原因:设备还没开始广播,或手机权限没给全。 处理:串口确认有
BLUFI init finish(广播在初始化完成回调里才启动);Android 检查蓝牙 + 位置权限;仍无果就断电重启设备。现象:App 报配网失败,错误码 0x00 / 0x01(sequence / checksum error)原因:两端帧序或校验基线不一致,常见于设备固件与 App 版本不匹配。 处理:断开 BLE 重新连接(序列号会清零重来),并确认 App 是最新版。
现象:密码填了就是连不上,App 显示失败原因原因:状态报告帧里带了
reason和RSSI,这是定位的关键。 处理:对照reason值查wifi_err_reason_t(如AUTH_EXPIRE基本可断定密码错);RSSI弱于 -75 就先换位置再试。现象:连接卡住十几秒才继续,或协商阶段出现
dh malloc error原因:无 MPI 硬件的芯片上 3072 位 DH 是软件运算,且需要约 4.2 KB 连续内部堆。 处理:卡住属正常等待;malloc 失败则按示例的做法,在 Wi-Fi 和 BLE host 吃堆之前预留堆(blufi_dh_pregen_start())。现象:App 直接报数据格式错误原因:SSID 或密码长度 ≥ 32 字节,设备侧直接回
ESP_BLUFI_DATA_FORMAT_ERROR。 处理:检查并截短凭证。
顺带提醒:示例日志把密码明文打到串口,生产环境请删掉那行打印,并考虑用自定义回调替换演示级加密。
适用边界与替代方案
BluFi 的官方状态是维护模式:协议稳定、不再加新功能,支持 ESP32、C2、C3、C5、C6、C61、S3、S31,且仅限 2.4 GHz Wi-Fi。
- 该用它:已有生态要求 BluFi 协议、需要"设备主动扫描并把 Wi-Fi 列表推给手机"的体验、或想自己啃 GATT 配网协议时。
- 别用它:全新项目。官方推荐两条路——SoftAP 配网(配网期间设备开热点,实现简单但临时占用 Wi-Fi 模式),或
network_provisioning组件(基于 BLE 的现代方案,活跃维护)。
延伸阅读(仓库内相对路径):
- 协议细节与帧定义:docs/en/api-guides/ble/blufi.rst
- 完整示例工程:examples/bluetooth/blufi/
- 密钥协商与加解密实现:examples/bluetooth/blufi/main/blufi_security.c
【免费下载链接】esp-idfEspressif IoT Development Framework. Official development framework for Espressif SoCs.项目地址: https://gitcode.com/GitHub_Trending/es/esp-idf
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考