安全签名使用指南
安全性是物联网解决方案中至关重要的一环,保障设备的安全始终是核心考量。ESP32 系列 SoC(如 ESP32、ESP32-S3、ESP32-C3、ESP32-C6 等)支持安全启动,可确保设备只能运行经过合法签名的固件。
如需了解更多关于安全启动的信息,请参考 ESP IDF 文档。本指南仅介绍如何通过 ESP RainMaker 的安全签名功能启用安全启动,不涉及安全启动原理细节。
如需了解更多安全签名内容,请查阅此文档。
本用户指南需要用户访问 ESP RainMaker 管理面板。
总体流程
安全签名的整体流程如下:
在管理面板创建签名密钥
- 安全签名的第一步是创建密钥。可通过公有 RainMaker 管理面板 或私有部署的 RainMaker 管理面板完成。
- 进入
Key Management
密钥管理页面,点击右上角Generate New Key
生成新密钥。 - 输入自定义名称和描述,选择算法并生成。
- 一般建议选择 RSA-3072 作为安全启动 v2 的算法。
(请查阅 IDF 文档确认平台支持的算法。)
密钥生成后,会在列表中显示相关信息。
在固件端生成固件镜像
为支持安全启动,需在 sdkconfig 中启用相应配置:
-
启用硬件安全启动(CONFIG_SECURE_BOOT),设置如下:
-
禁用
CONFIG_SECURE_BOOT_BUILD_SIGNED_BINARIES
,因为签名将在云端完成,设置如下: -
可选:启用 flash 加密
CONFIG_SECURE_FLASH_ENC_ENABLED
,设置如下: -
将分区表偏移
CONFIG_PARTITION_TABLE_OFFSET
设置为0xC000
,如下: -
选择
partitions_4mb_optimised.csv
作为分区表CONFIG_PARTITION_TABLE_CUSTOM_FILENAME
,设置如下:这是因为默认 RainMaker 分区大小不足。启用安全启动后,镜像体积会因额外代码、填充和签名而增大。
-
使用
idf.py build
构建项目。
镜像签名
启用安全启动前,需要对引导加载程序和固件镜像进行签名。
后续 OTA 固件升级时,仅需对固件镜像签名。
在固件端
编译完成后,相关文件位于项目目录:
组件 | 路径 |
---|---|
固件 | build/<project_name>.bin |
引导加载程序 | build/bootloader/bootloader.bin |
签名步骤如下:
- 在 RainMaker 管理面板进入
Firmware Images
页面,点击右上角Add Image
。 - 填写友好名称和设备类型。
- 点击
Advanced
查看安全签名选项。 - 从下拉列表选择前面创建的密钥。
- 选择引导加载程序镜像。
第 5 步仅在首次启用安全启动时需要,后续 OTA 无需此操作。
- 点击
Add Image
并等待。 - 固件和引导加载程序镜像将被上传并签名,成功后会显示如下提示:
- 点击
Show signed images details
显示可下载烧录的签名镜像。
- 也可在固件镜像页面点击
Image name
进入详情页下载。
在固件端启用安全启动
获取签名镜像后,需与分区表、ota_data_initial.bin、fctry binary 等其他二进制文件一起烧录。示例命令:
python -m esptool --chip esp32c3 -b 460800 --before default_reset --after no_reset --no-stub -p /dev/tty.usbserial-110 write_flash --flash_mode dio --flash_size keep --flash_freq 80m 0xc000 build/partition_table/partition-table.bin 0x16000 build/ota_data_initial.bin 0x20000 secure_boot/c3/Secure\ Boot\ Light\ C3_signed.bin 0x0 secure_boot/c3/bootloader_signed.bin
secure_boot/c3/Secure\ Boot\ Light\ C3_signed.bin
和 secure_boot/c3/bootloader_signed.bin
为前述下载的签名镜像。
首次启动后,日志应类似如下,表明安全启动 v2 已启用:
I (146) esp_image: segment 0: paddr=00020020 vaddr=3c130020 size=4d7e8h (317416) map
I (207) esp_image: segment 1: paddr=0006d810 vaddr=3fc97000 size=02808h ( 10248) load
I (209) esp_image: segment 2: paddr=00070020 vaddr=42000020 size=1206cch (1181388) map
I (408) esp_image: segment 3: paddr=001906f4 vaddr=3fc99808 size=00f78h ( 3960) load
I (410) esp_image: segment 4: paddr=00191674 vaddr=40380000 size=16e2ch ( 93740) load
I (433) esp_image: segment 5: paddr=001a84a8 vaddr=00000000 size=07b28h ( 31528)
I (438) esp_image: Verifying image signature...
I (439) secure_boot_v2: Secure boot V2 is not enabled yet and eFuse digest keys are not set
I (444) secure_boot_v2: Verifying with RSA-PSS...
I (452) secure_boot_v2: Signature verified successfully!
I (462) boot: Loaded app from partition at offset 0x20000
I (502) boot: Set actual ota_seq=1 in otadata[0]
I (502) secure_boot_v2: enabling secure boot v2...
I (503) efuse: Batch mode of writing fields is enabled
I (508) esp_image: segment 0: paddr=00000020 vaddr=3fcd5990 size=032f4h ( 13044)
I (518) esp_image: segment 1: paddr=0000331c vaddr=403cc710 size=00b9ch ( 2972)
I (524) esp_image: segment 2: paddr=00003ec0 vaddr=403ce710 size=05330h ( 21296)
I (535) esp_image: Verifying image signature...
I (538) secure_boot_v2: Secure boot V2 is not enabled yet and eFuse digest keys are not set
I (547) secure_boot_v2: Verifying with RSA-PSS...
I (555) secure_boot_v2: Signature verified successfully!
I (558) secure_boot_v2: Secure boot digests absent, generating..
I (571) secure_boot_v2: Digests successfully calculated, 1 valid signatures (image offset 0x0)
I (574) secure_boot_v2: 1 signature block(s) found appended to the bootloader.
I (581) secure_boot_v2: Burning public key hash to eFuse
I (590) efuse: Writing EFUSE_BLK_KEY0 with purpose 9
I (741) secure_boot_v2: Digests successfully calculated, 1 valid signatures (image offset 0x20000)
I (741) secure_boot_v2: 1 signature block(s) found appended to the app.
I (747) secure_boot_v2: Application key(0) matches with bootloader key(0).
I (754) secure_boot_v2: Revoking empty key digest slot (1)...
I (761) secure_boot_v2: Revoking empty key digest slot (2)...
I (767) secure_boot_v2: blowing secure boot efuse...
I (773) secure_boot: Enabling Security download mode...
I (779) secure_boot: Disable hardware & software JTAG...
I (785) secure_boot: Prevent read disabling of additional efuses...
I (793) efuse: BURN BLOCK4
I (799) efuse: BURN BLOCK4 - OK (write block == read block)
I (801) efuse: BURN BLOCK0
I (807) efuse: BURN BLOCK0 - OK (all write block bits are set)
I (811) efuse: Batch mode. Prepared fields are committed
I (817) secure_boot_v2: Secure boot permanently enabled
后续启动时,日志会简化,仅提示安全启动 v2 已启用。
I (180) esp_image: segment 0: paddr=00020020 vaddr=3c130020 size=4d7e8h (317416) map
I (241) esp_image: segment 1: paddr=0006d810 vaddr=3fc97000 size=02808h ( 10248) load
I (244) esp_image: segment 2: paddr=00070020 vaddr=42000020 size=1206cch (1181388) map
I (443) esp_image: segment 3: paddr=001906f4 vaddr=3fc99808 size=00f78h ( 3960) load
I (444) esp_image: segment 4: paddr=00191674 vaddr=40380000 size=16e2ch ( 93740) load
I (467) esp_image: segment 5: paddr=001a84a8 vaddr=00000000 size=07b28h ( 31528)
I (472) esp_image: Verifying image signature...
I (473) secure_boot_v2: Verifying with RSA-PSS...
I (477) secure_boot_v2: Signature verified successfully!
I (487) boot: Loaded app from partition at offset 0x20000
I (487) secure_boot_v2: enabling secure boot v2...
I (492) secure_boot_v2: secure boot v2 is already enabled, continuing..
安全启动密钥摘要
安全启动启用后,RainMaker 固件会在节点配置的 info.secure_boot_digest 字段中上报安全启动公钥的 sha256 校验值,如下所示:
{
"node_id": "1091A8AABBCC",
"config_version": "2020-03-20",
"info": {
"name": "ESP RainMaker Device",
"fw_version": "1.1",
"type": "Lightbulb",
"model": "led_light",
"project_name": "led_light",
"platform": "esp32c3",
"secure_boot_digest": {
"k0": "a1d634140fc4922639da85206fe73de6fee9b3c62319318cf7545cf79f200faa",
"k1": null,
"k2": null
}
}
}
后端可据此查找节点所用签名密钥,便于 OTA 升级。
OTA 升级
OTA 升级时,固件镜像需按上述说明构建,但上传时可不选择签名密钥。上传后,在固件镜像列表右侧点击 Start OTA
,在弹窗中填写 OTA 任务名,选择节点/分组,勾选 Secure Boot
。
随后可选择以下两种方式之一:
方式 | 说明 |
---|---|
自动选择密钥 | 仅适用于非“强制推送”任务。节点请求 OTA 时,后端根据节点配置上报的摘要自动查找密钥并签名镜像,避免签名密钥错误。适用于不同节点使用不同密钥但固件相同的场景。 |
手动签名 | 适用于所有 OTA 任务,包括强制推送。手动选择签名密钥,后端用该密钥签名镜像并下发,不校验节点上报的摘要。 |
根据实际需求选择方式并启动 OTA。在 OTA 详情页可看到 Secure boot: yes
,也可查看签名镜像详情。如适用,还会显示 auto select key
。
OTA 状态可在同一页面查看,与普通 OTA 任务一致。