硬汉嵌入式论坛

 找回密码
 立即注册
查看: 618|回复: 5
收起左侧

[脱机烧录] H7-TOOL脱机烧录的UID签名操作说明,采用ECDSA SECP256R1验证,哈希值计算使用的SHA224(2026-04-10,已经更新)

[复制链接]

1万

主题

7万

回帖

12万

积分

管理员

Rank: 9Rank: 9Rank: 9

积分
122321
QQ
发表于 2026-2-28 00:55:32 | 显示全部楼层 |阅读模式
实现机制:

直接对芯片UID进行签名,将签名作为"芯片证书"

1、原始UID → 签名 → 带签名的UID → 存储到芯片
验证时:验证签名 + 检查UID是否匹配

2、ECDSA是基于椭圆曲线密码学的数字签名算法,用于验证数据的真实性和完整性。它比传统的RSA更安全且密钥更短。

操作说明:

1、使用H7-TOOL的硬件随机数生成公钥和私钥,当然也可以自己提供,均支持

将下面代码复制到LUA小程序页面生成相应数组

[Lua] 纯文本查看 复制代码
local s = ""
local Private_KeySize = 32 -- 私钥长度为32字节
local Public_KeySize = 64  -- 公钥长度为64字节
local SignSize = 64        -- ECDSA签名长度为64字节
local ENCRYPT_LEN = 128    -- 签名长度 + 公钥长度,固定128字节
local Private_Key = {}
local Public_Key = {}

local re
local uid = {}
local x = {}
local sign = {}

-- 依次返回私钥, 公钥和成功状态
Private_Key, Public_Key, re = cmox_ecdsa_keyGen()
if(re == 1) then
    --print("cmox_ecdsa_keyGen success")
else
    print(sring.format("cmox_ecdsa_keyGen fail, re = %d", re))
end

print("ENCRYPT_LEN = ", ENCRYPT_LEN)

----------------打印私钥----------------------------
Private_KeySize = #Private_Key
print("Private_KeySize = ", Private_KeySize)
s = "Private_Key = {\n"
for i=1, Private_KeySize, 1 do                                
    s =s..string.format("0x%02x", Private_Key[i])..","
    if i % 16 == 0 then
        s = s.."\n"
    end                                
end
s =s.."}\n"
print(s) 

---------------打印公钥-----------------------------
Public_KeySize = #Public_Key
print("Public_KeySize = ", Public_KeySize)
s = "Public_Key = {\n"
for i=1, Public_KeySize, 1 do                                
    s =s..string.format("0x%02x", Public_Key[i])..","
    if i % 16 == 0 then
        s = s.."\n"
    end                                
end
s =s.."}\n"
print(s) 


1243.png

2、脱机烧录时读取芯片UID → 计算哈希值 → 生成签名 → 带签名的UID和公钥 → 脱机烧录存储到芯片

这里以为我们STM32-V7开发板,主控芯片STM32H743/H750为例进行说明。

(1)脱机烧录页面选择型号,加载要烧录的固件

123.png

(2)选择对应的算法

13.png

并设置签名要烧录到的地址0x08100000,  写入到#1区

23.png

然后分区就是这个意思



(3)高级脚本里面,添加公钥和私钥,私钥仅存储于TOOL端,公钥是供芯片端校验签名使用的

12.png

3、芯片端运行相同的算法,通过公钥和签名验证是否通过校验。

(1)烧录一个带签名校验的固件到目标芯片

2334.png

(2)方便观察现象,芯片端例子做了个RTT打印,验证通过

23.png

4、配套例子,方便参考

基于STM32H7板子,配套了IAR,MDK AC5和AC6的例子

V7-SIG.7z (14.42MB)


参考资料:

H7-TOOL的LUA小程序教程第18期:ECDSA签名私钥公钥生成,签名和校验LUA函数(2026-04-10)
https://forum.anfulai.cn/forum.php?mod=viewthread&tid=131338
回复

使用道具 举报

1万

主题

7万

回帖

12万

积分

管理员

Rank: 9Rank: 9Rank: 9

积分
122321
QQ
 楼主| 发表于 2026-2-28 10:48:49 | 显示全部楼层
UID签名相当于身份证,烧录到这个芯片里面的固件仅可以在这个芯片里面使用,芯片级软硬件绑定
回复

使用道具 举报

4

主题

145

回帖

157

积分

初级会员

积分
157
QQ
发表于 2026-2-28 14:39:31 | 显示全部楼层
配合h7 tool的脱机烧录、烧录计数、远程管理和emmc加密功能,可以非常方便的把h7 tool交给代工厂去生产烧录
回复

使用道具 举报

1万

主题

7万

回帖

12万

积分

管理员

Rank: 9Rank: 9Rank: 9

积分
122321
QQ
 楼主| 发表于 2026-3-1 00:43:32 | 显示全部楼层
优化了下函数,方便调用。
回复

使用道具 举报

1万

主题

7万

回帖

12万

积分

管理员

Rank: 9Rank: 9Rank: 9

积分
122321
QQ
 楼主| 发表于 2026-3-2 00:28:59 | 显示全部楼层
最终版

本周更新对应的LUA API教程和UID签名教程

[Lua] 纯文本查看 复制代码
local s = ""
local Private_KeySize = 32
local Public_KeySize = 64
local Private_Key = {}
local Public_Key = {}

local re
local uid = {}
local x = {}
local sign = {}

-- 返回私钥, 公钥和成功状态
Private_Key, Public_Key, re = cmox_ecdsa_keyGen()
if(re == 1) then
    print("cmox_ecdsa_keyGen success")
else
    print("cmox_ecdsa_keyGen fail")
end
----------------打印私钥----------------------------
Private_KeySize = #Private_Key
print("Private_KeySize = ", Private_KeySize)
s = "Private_Key = {\n"
for i=1, Private_KeySize, 1 do                                
    s =s..string.format("0x%02x", Private_Key[i])..","
    if i % 16 == 0 then
        s = s.."\n"
    end                                
end
s =s.."}\n"
print(s) 

---------------打印公钥-----------------------------
Public_KeySize = #Public_Key
print("Public_KeySize = ", Public_KeySize)
s = "Public_Key = {\n"
for i=1, Public_KeySize, 1 do                                
    s =s..string.format("0x%02x", Public_Key[i])..","
    if i % 16 == 0 then
        s = s.."\n"
    end                                
end
s =s.."}\n"
print(s) 

---------------读取UID----------------------------
re, uid = pg_read_uid(0x1FF1E800)  -- 这里是读取的STM32H7的UID地址,其他芯片需要修改地址
if(re == 1) then
    print("pg_read_uid success")
else
    print("pg_read_uid fail")
    uid = {0,1,2,3, 4,5,6,7, 8,9,10,11} -- 随意定义一个,用于测试
end

for i = 1, #uid do
   x[i] = string.byte(uid, i)
end

---------------求签名----------------------------
sign, re = cmox_ecdsa_sign(Private_Key, Private_KeySize, x, #uid)

if(re == 1) then
    print("cmox_ecdsa_sign success")
    print("SignSize = ", #sign)
    s = "Sign = {\n"
    for i=1, #sign, 1 do                                
        s =s..string.format("0x%02x", sign[i])..","
        if i % 16 == 0 then
            s = s.."\n"
        end                                
    end
    s =s.."}\n"
    print(s) 
else
    print("cmox_ecdsa_sign fail")
end

---------------验证签名----------------------------
re = cmox_ecdsa_verify(Public_Key, Public_KeySize, x, #uid, sign, #sign)
if(re == 1) then
    print("cmox_ecdsa_verify success")
else
    print("cmox_ecdsa_verify fail")
end




234.png
回复

使用道具 举报

1万

主题

7万

回帖

12万

积分

管理员

Rank: 9Rank: 9Rank: 9

积分
122321
QQ
 楼主| 发表于 2026-4-11 00:15:48 | 显示全部楼层
已经更新操作说明
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

QQ|小黑屋|Archiver|手机版|硬汉嵌入式论坛

GMT+8, 2026-5-1 05:08 , Processed in 0.257524 second(s), 30 queries .

Powered by Discuz! X3.4 Licensed

Copyright © 2001-2023, Tencent Cloud.

快速回复 返回顶部 返回列表