ESP32之蓝牙配网blufi

2023-05-16

概览

BluFi 是一款基于蓝牙通道的 Wi-Fi 网络配置功能,适用于 ESP32。它通过安全协议将 Wi-Fi 配置和证书传输到 ESP32,然后 ESP32 可基于这些信息连接到 AP 或建立 SoftAP。

BluFi 流程的关键部分包括数据的分片、加密、校验和验证。

用户可按需自定义用于对称加密、非对称加密和校验的算法。这里我们采用 DH 算法进行密钥协商、128-AES 算法用于数据加密、CRC16 算法用于校验和验证。

BluFi 流程

BluFi 配网功能包含配置 SoftAP 和 Station 两部分。

下面以配置 Station 为例说明配置步骤。 BluFi 配网的配置 Station 包含广播、连接、服务发现、协商共享密钥、传输数据、回传连接状态等步骤。

ESP32 配网流程

  1. ESP32 开启 GATT Server 功能,发送带有特定 adv data 的广播。你可以自定义该广播,该广播不属于 BluFi Profile。
  2. 使用手机 APP 搜索到该特定广播,手机作为 GATT Client 连接 ESP32。你可以决定使用哪款手机 APP。
  3. GATT 连接建立成功后,手机向 ESP32 发送“协商过程”数据帧(详情见 BluFi 传输格式 )。
  4. ESP32 收到“协商过程”数据帧后,会按照使用者自定义的协商过程来解析。
  5. 手机与 ESP32 进行密钥协商。协商过程可使用 DH/RSA/ECC 等加密算法进行。
  6. 协商结束后,手机端向 ESP32 发送“设置安全模式”控制帧。
  7. ESP32 收到“设置安全模式”控制帧后,使用经过协商的共享密钥以及配置的安全策略对通信数据进行加密和解密。
  8. 手机向 ESP32 发送“BluFi 传输格式”定义的 SSID、Password 等用于 Wi-Fi 连接的必要信息。
  9. 手机向 ESP32 发送“Wi-Fi 连接请求”控制帧,ESP32 收到之后,识别为手机已将必要的信息传输完毕,准备连接 Wi-Fi。
  10. ESP32 连接到 Wi-Fi 后,发送“Wi-Fi 连接状态报告”控制帧到手机,以报告连接状态。至此配网结束。

注解

  1. 安全模式设置可在任何时候进行,ESP32 收到安全模式的配置后,会根据安全模式指定的模式进行安全相关的操作。
  2. 进行对称加密和解密时,加密和解密前后的数据长度必须一致,支持原地加密和解密。

配网流程图

BluFi Flow Chart

BluFi 传输格式

手机 APP 与 ESP32 之间的 BluFi 通信格式定义如下:

帧不分片情况下的标准格式 (8 bit):

DescriptionValue
LSB - Type1
Frame Control1
Sequence Number1
Data Length1
Data${Data Length}
MSB - CheckSum2

如果 Frame Control 帧中的 More Frag 使能,则 Total Content Length 为数据帧中剩余部分的总长度,用于报告终端需要分配多少内存。

帧分片格式(8 bit):

DescriptionValue
LSB - Type1
FrameControl(Frag)1
SequenceNumber1
DataLength1
DataTotal Content Length2
Content${Data Length} - 2
MSB - CheckSum2

通常情况下,控制帧不包含数据位,Ack 帧类型除外。

Ack 帧格式(8 bit):

DescriptionValue
LSB - Type (Ack)1
Frame Control1
SequenceNumber1
DataLength1
DataAcked Sequence Number2
MSB - CheckSum2
  1. Type

    类型域,占 1 byte。分为 Type 和 Subtype(子类型域)两部分, Type 占低 2 bit,Subtype 占高 6 bit。

    • 控制帧,暂不进行加密,可校验;
    • 数据帧,可加密,可校验。

1.1 控制帧 (0x0 b’00)

控制帧 (二进制)含义解释备注
0x0 (b’000000)Ack用来回复对方发的帧, Ack 帧的 Data 域使用回复对象帧的 Sequence 值。Data 域使用1 byte Sequence 值, 与恢复对象帧的Sequence 值相同。
0x1 (b’000001)Set ESP32 to the security mode.通知 ESP32 发送数据时使用的安全模式, 在该过程中可设置多次,每次设置后影响后续安全模式。 在不设置的情况下,ESP32 默认控制帧和数据帧均为无校验、无加密。 手机到 ESP32 方向依赖于帧 Control 域。Data 域占用 1 byte。 高 4 bit 为控制帧的安全模式,低 4bit 为数据帧的安全模式。
b’0000:无校验、无加密;
b’0001:有校验、无加密;
b’0010:无校验、有加密;
b’0011:有校验、有加密。
0x2 (b’000010)Set the Wi-Fi opmode of ESP32.设置 ESP32 的 Wi-Fi 模式,帧包含 opmode 信息。data[0] 用于表示 opmode 类型,包括:
0x00: NULL;
0x01: STA;
0x02: SoftAP;
0x03: SoftAP&STA.
如果设置有包含 AP,请尽量优先 设置 AP 模式的SSID/Password/Max Conn Number 等。
0x3 (b’000011)Connect ESP32 to the AP.通知 ESP32,必要的信息已经发送完毕,可以连接 AP。不包含 Data 域。
0x4 (b’000100)Disconnect ESP32 from the AP.通知 ESP32 断开与 AP 的连接不包含 Data 域。
0x5 (b’000101)Get the status of Wi-Fi.获取 ESP32 的 Wi-Fi 模式和状态等信息。不包含 Data 域。 ESP32 收到此控制帧后,后续会通过 Wi-Fi 连接状态 报告 (Wi-Fi Connection State Report) 数据帧来回复手机端当前 所处的 opmode、连接状态、SSID 等信息。提供给手机端的信息由应用决定。
0x6 (b’000110)Disconnect the STA device from the SoftAP in SoftAP mode.处于 SoftAP 模式时,踢掉某个 STA 设备。data[0~5] 为 STA 设备的 MAC 地址, 如有多个 STA,则 [6-11] 为第二个,依次类推。
0x7 (b‘000111)Get the version.  
0x8 (b’001000)Tell ESP32 to disconnect the BLE GATT link.通知 ESP32 断开蓝牙连接。ESP32 收到该指令后主动断开蓝牙连接。
0x9 (b’001001)Tell ESP32 to get the Wi-Fi list.通知 ESP32 扫描周围的 Wi-Fi 热点不包含 Data 域。 ESP32 收到此控制帧后,会发送包含 Wi-Fi 热点 报告 (Wi-Fi List Report) 的数据帧回复 手机端 ESP32 周围的 Wi-Fi 热点。

1.2 数据帧 (0x1 b’01)

数据帧 (二进制)含义解释备注
0x0 (b’000000)Negotiation data.用来发送协商数据,传输到应用层注册的回调函数。数据长度与 Length 域有关。
0x1 (b’000001)BSSID for STA mode.STA 将要连接的 AP 的 BSSID(用于隐藏SSID)。数据长度与 Length 域有关。
当传输方向为 ESP32 到手机时, 表示向手机端提供信息。
0x2 (b’000010)SSID for STA mode.STA 将要连接的 AP 的 SSID。数据长度与 Length 域有关。
当传输方向为 ESP32 到手机时, 表示向手机端提供信息。
0x3 (b’000011)Password for STA mode.STA 将要连接的 AP 的密码。数据长度与 Length 域有关。
当传输方向为 ESP32 到手机时, 表示向手机端提供信息。
0x4 (b’000100)SSID for SoftAP mode.SoftAP 模式使用的 SSID。数据长度与 Length 域有关。
当传输方向为 ESP32 到手机时, 表示向手机端提供信息。
0x5 (b’000101)Password for SoftAPmode.SoftAP 模式使用的密码。数据长度与 Length 域有关。
当传输方向为 ESP32 到手机时, 表示向手机端提供信息。
0x6 (b’000110)Max connection number for SoftAP mode.AP 模式的最大连接数。data[0] 表示连接数的值,范围 1~4。
当传输方向为 ESP32 到手机时, 表示向手机端提供信息。
0x7 (b’000111)Authentication mode for SoftAP mode.AP 模式的认证模式。data[0]:
0x00: OPEN;
0x01: WEP;
0x02: WPA_PSK;
0x03: WPA2_PSK;
0x04: WPA_WPA2_PSK.
当传输方向为 ESP32 到手机时, 表示向手机端提供信息。
0x8 (b’001000)Channel for SoftAP mode.SoftAP 模式的通道数量。data[0] 表示通道的数量,范围 1~14。
当传输方向为 ESP32 到手机时, 表示向手机端提供信息。
0x9 (b’001001)Username.使用企业级加密时,Client 端的用户名。数据长度与 Length 域有关。
0xa (b’001010)CA certification.进行企业级加密时使用的 CA 证书。数据长度与 Length 域有关, 长度不够,可用分片。
0xb (b’001011)Client certification.进行企业级加密时,Client 端的证书。数据长度与 Length 域有关, 长度不够,可用分片。
可包含或不包含私钥,由证书内容决定。
0xc (b’001100)Server certification.进行企业级加密时,Server 端的证书。数据长度与 Length 域有关, 长度不够,可用分片。
可包含或不包含私钥,由证书内容决定。
0xd (b’001101)Client private key.进行企业级加密时,Client 端的私钥。数据长度与 Length 域有关, 长度不够,可用分片。
0xe (b’001110)Server private key.进行企业级加密时,Server 端的私钥。数据长度与 Length 域有关, 长度不够,可用分片。
0xf (b’001111)Wi-Fi connection state report.通知手机 ESP32 的 Wi-Fi 状态, 包括 STA状态和 SoftAP 状态, 用于手机配置 STA 连接时的通知, 或有 STA 连接上 SoftAP 时的通知。data[0] 表示 opmode,包括:
但收到手机询问 Wi-Fi 状态时, 除了回复此帧外,还可回复其他数据帧。0x00: NULL;
0x01: STA;
0x02: SoftAP;
0x03: SoftAP&STA
data[1]:STA 的连接状态, 0x0 表示处于连接状态, 其他表示处于非连接状态;
data[2]:SoftAP 的连接状态, 即表示有多少 STA 已经连接。
data[3] 及以后:为按照本协议格式 SSIDBSSID 等信息。
0x10 b’010000Version. data[0]= great version
data[1]=sub version
0x11 (b’010001)Wi-Fi list.通知手机 ESP32 周围的 Wi-Fi 热点列表。数据帧数据格式为 Length + RSSI + SSID, 数据较长时可分片发送。
0x12 (b’010010)Report error.通知手机 BluFi 过程出现异常错误。0x00: sequence error;
0x01: checksum error;
0x02: decrypt error;
0x03: encrypt error;
0x04: init security error;
0x05: dh malloc error;
0x06: dh param error;
0x07: read param error;
0x08: make public error.
0x13 (b’010011)Custom data.用户发送或者接收自定义数据。数据较长时可分片发送。
  1. Frame Control

    帧控制域,占 1 byte,每个 bit 表示不同含义。

    含义
    0x01表示帧是否加密。
    1 表示加密,0 表示未加密。
    加密部分帧括完整的 DATA 域加密之前的明文(不帧含末尾的校验)。
    控制帧暂不加密,故控制帧此位为 0。
    0x02表示帧 Data 域结尾是否帧含校验(例如 SHA1,MD5,CRC等)需要校验的数据域包括 sequcne + data length + 明文 data。
    控制帧和数据帧都可以包含校验位或不包含。
    0x04表示数据方向。
    0 表示手机发向 ESP32;
    1 表示 ESP32 发向手机。
    0x08表示是否要求对方回复 ack。
    0 表示不要求;
    1 表示要求回复 ack。
    0x10表示是否有后续的数据分片。
    0 表示此帧没有后续数据分片;
    1 表示还有后续数据分片,用来传输较长的数据。
    如果是 Frag 帧,则告知当前 content 部分+后续 content 部分的总长度,位于 Data 域的前 2 字节(即最大支持 64K 的 content 数据)。
    0x10~0x80 保留 
  2. Sequence Control

    序列控制域。帧发送时,无论帧的类型是什么,序列 (Sequence) 都会自动加 1,用来防止重放攻击 (Replay Attack)。每次重现连接后,序列清零。

  3. Length

    Data 域的长度,不包含 CheckSum。

  4. Data

    不同的 Type 或 Subtype,Data 域的含义均不同。请参考上方表格。

  5. CheckSum

    此域为 2 byte 的校验,用来校验『序列 + 数据长度 + 明文数据』。

ESP32 端的安全实现

  1. 保证数据安全

    为了保证 Wi-Fi SSID 和密码的传输过程是安全的,需要使用对称加密算法(例如 AES、DES等)对报文进行加密。在使用对称加密算法之前,需要使用非对称加密算法(DH、RSA、ECC 等)协商出(或生成出)一个共享密钥。

  2. 保证数据完整性

    保证数据完整性,需要加入校验算法(例如 SHA1、MD5、CRC 等)。

  3. 身份安全(签名)

    某些算法如 RSA 可以保证身份安全。有些算法如 DH,本身不能保证身份安全,需要添加其他算法来签名。

  4. 防止重放攻击 (Replay Attack)

    加入帧发送序列(Sequence),并且序列参与数据校验。

    在 ESP32 端的代码中,你可以决定和开发密钥协商等安全处理的流程参考上述流程图)。手机应用向 ESP32 发送协商数据,将传送给应用层处理。如果应用层不处理,可使用 BluFi 提供的 DH 加密算法来磋商密钥。应用层需向 BluFi 注册以下几个与安全相关的函数:


typedef void (*esp_blufi_negotiate_data_handler_t)(uint8_t *data, int len, uint8_t **output_data, int *output_len, bool *need_free);
  

该函数用来接收协商期间的正常数据 (normal data),处理完成后,需要将待发送的数据使用 output_data 和 output_len 传出。

BluFi 会在调用完 negotiate_data_handler 后,发送 negotiate_data_handler 传出的 output_data。

这里的两个『*』,因为需要发出去的数据长度未知,所以需要函数自行分配 (malloc) 或者指向全局变量,通过 need_free 通知是否需要释放内存。


typedef int (* esp_blufi_encrypt_func_t)(uint8_t iv8, uint8_t *crypt_data, int cyprt_len);
  

加密和解密的数据长度必须一致。其中 iv8 为帧的 8 bit 序列 (sequence),可作为 iv 的某 8 bit 来使用。


typedef int (* esp_blufi_decrypt_func_t)(uint8_t iv8, uint8_t *crypt_data, int crypt_len);
  

加密和解密的数据长度必须一致。其中 iv8 为帧的 8 bit 序列 (sequence),可作为 iv 的某 8 bit 来使用。


typedef uint16_t (*esp_blufi_checksum_func_t)(uint8_t iv8, uint8_t *data, int len);
  

该函数用来计算 CheckSum,返回值为 CheckSum 的值。BluFi 会使用该函数返回值与包末尾的 CheckSum 做比较。

GATT 相关说明

UUID

BluFi Service UUID: 0xFFFF,16 bit

BluFi (手机 -> ESP32) 特性:0xFF01,主要权限:可写

BluFi (ESP32 -> 手机) 特性:0xFF02,主要权限:可读可通知

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

ESP32之蓝牙配网blufi 的相关文章

  • esp-idf的电源管理——电源管理组件

    1 电源锁和动态频率切换 1 1 什么是电源锁 先概括的介绍一下IDF电源管理组件中的电源锁与动态频率切换 对主机CPU有了解的都知道 像Intel的酷睿处理器有个睿频功能 CPU非常聪明 可以在繁忙 需要高性能 的时候抬高频率 在不忙的时
  • esp32添加头文件

    环境 linux idf vsode 前言 在按照官方教程安装完成后 虽然可以编译成功 但是有些函数找不到定义 而且强迫症看到波浪号也非常难受 方法 点击小灯泡 点击第一个选项 如下图所示 拉到底点击advanced settings 让v
  • 【ESP-Matter】matter协议学习笔记--以乐鑫方案为例

    matter协议学习笔记 以乐鑫方案为例 0 写在前边的话 1 matter 协议基本概念 2 设备间的本地自动化交互 2 1 同步控制的实例 2 2 异步通知 订阅 报告 3 桥接设备 4 thread 边界路由器 5 专业名词 0 写在
  • 深入分析 ESP32 的 WiFi 状态机

    本工程已托管到 GitHub 具体路径是 https github com tidyjiang8 esp32 projects tree master sta 在前一篇博客 让 ESP32 连接到你的 WiFi 热点 中 我们已经简单地分析
  • esp32 SPIFFS的使用

    读取方法 include FS h include SPIFFS h include AutoFile h void File Init SPIFFS begin true 挂载 时间较长 void contentWrite String
  • esp32-S3专题一:初识esp32

    初识esp32 S3 初识esp32 使用esp32 s3这款芯片开发接近一年了 分享一下开发中的一些经验和项目中的亮点 希望后人能从中借鉴到一些经验 一 优势和缺点 使用的是esp32 s3这款芯片 硬件上搭配300k的RAM的代码运行内
  • Arduino IDE编译烧写ESP32 CAM

    一 安装Arduino IED 到官网下载IDE 二 安装ESP32 工具 打开菜单 文件 首选项 在设置页 附加开发板管理器网址 添加 https dl espressif com dl package esp32 index json
  • 【GUI】LVGL8内存泄漏分析

    LVGL版本 V8 0 2 平台 ESP32S3 在调试过程中 发现有两个界面 在重复退出再进入时内存会不断增加的吃内存现象 然后做了分析和研究 1 样式style吃内存 在主页面 进入simple页面 再退出到主页面 再次进入simple
  • ESP32 ADC –使用Arduino IDE读取模拟值

    本文介绍了如何使用Arduino IDE通过ESP32读取模拟输入 模拟读取对于从电位计或模拟传感器等可变电阻读取值非常有用 模拟输入 ADC ADC是非线性的 analogRead 函数 其他有用的功能 使用ESP32从电位计读取模拟值
  • micropython RX8025T 驱动简单演示

    我就知道可能八百年会有一位大哥来找这个驱动 让我来猜猜为啥用这个 嫌一般的RTC不够精准是吧 想用个带温度补偿的试试 代码拿去 其实巨简单的 没啥好说的 而且只有基本功能 from micropython import const impo
  • esp32-S3专题二:内存2之RTC内存、FLASH使用

    承接上文 讲一下esp32上剩下的几个存储空间的用途 目录 一 RTC存储器 一 RTC 快速存储器 二 RTC 慢速存储器 二 Flash 一 NVS 表 二 程序和OTA分区 三 SPIFFS 文件系统 三 总结 一 RTC存储器 es
  • C#驱动ESP32控制机器臂

    物料清单 介绍 NET nanoFramework 是一个免费的开源平台 可以为受限嵌入式设备编写托管代码应用程序 它适用于多种类型的项目 包括物联网传感器 可穿戴设备 学术概念验证 机器人技术 业余爱好者 创客创作甚至复杂的工业设备 通过
  • ESP32-C3 应用 篇(实例二、通过蓝牙将传感器数据发送给手机,手机端控制 SK6812 LED)

    ESP32 C3 蓝牙部分我们学习了GATT 本文尝试使用蓝牙做一个简单的小应用 目录 前言 一 整体框架 二 数据传输部分 2 1 添加温湿度驱动组件 2 2 传感器数据传输程序 再次说明 ESP GATTS READ EVT 事件 2
  • 个人对智能家居平台选择的思考

    本人之前开发过不少MicroPython程序 其中涉及到自动化以及局域网控制思路 也可以作为智能家居的实现方式 而NodeMCU ESPHome的方案具有方便添加硬件 容易更新程序和容量占用小的优势 本人也查看过相关教程后感觉部署ESPHo
  • ESP32开发板手动更换外置的flash

    ESP32开发板手动更换外置的flash 实物板 风险提示 操作有风险 需谨慎 新手请勿模仿 第一步拿下屏蔽罩 用热风枪 360 吹下来的 第二步 更换flash芯片 ESP32 D0WDQ6芯片下方那个就是flash芯片了型号 25VQ3
  • 启明云端分享

    提示 启明云端从2013年起就作为Espressif 乐鑫科技 大中华区合作伙伴 我们不仅用心整理了你在开发过程中可能会遇到的问题以及快速上手的简明教程 同时也用心推出了基于乐鑫的相关应用方案 希望你能第一时间了解并快速用上好的方案和产品
  • 在 esp32 上运行 lvgl + freetype

    前言 最近有个需求 如何在 esp32 上运行 lvgl freetype 这个想法的难点是 freetype 的环境搭建 我想将其做得非常简单 最好的办法是做成组件来使用 所以我将 freetype 的相关依赖做成了 esp idf 组件
  • ESP32学习笔记05-串口事件方式读取数据

    串口中断方式处理数据 事件机构体 typedef struct uart event type t type lt UART event type size t size lt UART data size for UART DATA ev
  • ESP-IDF库开发教程之(4)--FLASH、BootLoader和FreeRTOS

    在之前的文章中 我描述了新的esp32芯片 并解释了如何设置开发环境 包括使用一种可选的图形IDE Eclipse 在开始开发程序之前 您需要了解框架的三个关键组件 flash bootloader和FreeRTOS操作系统 但别担心 在本
  • 使用什么 ffmpeg 命令将无符号整数列表转换为音频文件?

    我有一个文件 其中包含大约四万个整数的列表 这些整数以空格分隔 每个整数的值都在 0 到 255 之间 这里是这个文件 https github com johnlai2004 sound project blob master integ

随机推荐