硬汉嵌入式论坛

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

[算法] 分享基于STM32H7的ECDSA算法的UID签名案例,含MDK AC5, AC6和IAR

[复制链接]

1万

主题

7万

回帖

12万

积分

管理员

Rank: 9Rank: 9Rank: 9

积分
121991
QQ
发表于 5 小时前 | 显示全部楼层 |阅读模式
硬件平台

基于STM32-V7开发板

案例下载
V7-SIG.7z (14.42MB)

实现机制

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

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

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

[C] 纯文本查看 复制代码
/*
*********************************************************************************************************
*
*        模块名称 : 主程序模块。
*        文件名称 : main.c
*        版    本 : V1.0
*        说    明 : ECDSA算法的UID验证
*             
*   注意实现 : 1、ECDSA使用的曲线是SECP256R1
*              2、哈希值计算使用的SHA224
*        修改记录 : 
*                版本号    日期        作者     说明
*                V1.0    2026-03-02   armfly    首发
*
*        Copyright (C), 2026-2030, 安富莱电子 [url=http://www.armfly.com]www.armfly.com[/url]
*
*********************************************************************************************************
*/
#include "bsp.h"                        /* 底层硬件驱动 */
#include "SEGGER_RTT.h"
#include "cmox_crypto.h"



/*
*********************************************************************************************************
*                                           变量和函数
*********************************************************************************************************
*/
cmox_ecc_handle_t Ecc_Ctx;                    /* ECC 上下文 */
uint8_t Working_Buffer[2000];                 /* ECC 工作缓冲区 */
uint8_t Computed_Hash[CMOX_SHA224_SIZE];      /* 计算哈希值 */
uint8_t Signature[CMOX_ECC_SECP256R1_SIG_LEN];/* 记录签名 */
uint8_t Public_Key[64];                       /* 公钥 */
uint8_t uid[12];                              /* UID缓冲 */
cmox_hash_retval_t  hretval;                  /* 哈希值计算返回状态 */                  
cmox_ecc_retval_t   retval;                   /* ECDSA校验返回状态*/
size_t                                 computed_size;            /* 哈希值返回值个数记录*/
uint32_t fault_check = CMOX_ECC_AUTH_FAIL;          /* ECDSA异常记录*/

/* 打印数组函数,按每行16个字节的格式输出 */ 
void print_array_16_per_line(const char *name, const uint8_t *array, size_t len) 
{
    SEGGER_RTT_printf(0, "%s:\n", name);
    for (size_t i = 0; i < len; i++) 
    {
        /* 打印每个字节,以两位十六进制形式显示 */ 
        SEGGER_RTT_printf(0, "0x%02X", array);
        
        /* 每行16个元素后换行,或者最后一个元素后也换行 */ 
        if ((i + 1) % 16 == 0 || i == len - 1) 
        {
            SEGGER_RTT_printf(0, "\n");
        } 
        else 
        {
            SEGGER_RTT_printf(0, " ");
        }
    }
    SEGGER_RTT_printf(0, "\n"); /* 额外空行分隔两个数组 */ 
}

/*
*********************************************************************************************************
*        函 数 名: main
*        功能说明: c程序入口
*        形    参:无
*        返 回 值: 错误代码(无需处理)
*********************************************************************************************************
*/
int main(void)
{
        uint8_t ucKeyCode;        

        bsp_Init();                /* 硬件初始化 */

        /* 配置通道0,上行配置*/
        SEGGER_RTT_ConfigUpBuffer(0, "RTTUP", NULL, 0, SEGGER_RTT_MODE_NO_BLOCK_SKIP);
        
        /* 配置通道0,下行配置*/        
        SEGGER_RTT_ConfigDownBuffer(0, "RTTDOWN", NULL, 0, SEGGER_RTT_MODE_NO_BLOCK_SKIP);
    
        /*第1步:读取UID,签名和公钥 =========================================================*/
    /* (1) STM32H7的UID读取,12个字节 */
    for(int i = 0; i < sizeof(uid); i++)
    {
        uid = *(__IO uint8_t*)(0x1FF1E800 + i);
    }
    
    print_array_16_per_line("uid", uid, 12);
    
    /* (2) 读取签名值,64个字节 */
    for(int i = 0; i < CMOX_ECC_SECP256R1_SIG_LEN; i++)
    {
        Signature = *(__IO uint8_t*)(0x08100000 + i);
    }
    
    print_array_16_per_line("Signature", Signature, 64);
    
    /* (3) 读取公钥,64个字节 */    
    for(int i = 0; i < 64; i++)
    {
        Public_Key = *(__IO uint8_t*)(0x08100000 + i + CMOX_ECC_SECP256R1_SIG_LEN);
    }
    
     print_array_16_per_line("Public_Key", Public_Key, 64);
    
        /*第2步:初始化加密库 =======================================================================*/
        cmox_init_arg_t init_target = {CMOX_INIT_TARGET_AUTO, NULL};
        
        if (cmox_initialize(&init_target) != CMOX_INIT_SUCCESS)
        {
                SEGGER_RTT_printf(0, "初始化失败\r\n");
        }
        
    /*第3步:计算哈希值(摘要) ================================================================*/
        /* 通过传入所有必要参数直接计算摘要 */
        hretval = cmox_hash_compute(CMOX_SHA224_ALGO,          /* 使用SHA224算法 */
                                                              uid,  sizeof(uid),       /* 待计算摘要的消息 */
                                  Computed_Hash,           /* 接收摘要数据的缓冲区 */
                                  CMOX_SHA224_SIZE,        /* 预期的摘要大小 */
                                  &computed_size);         /* 计算得到的摘要大小 */

        /* 验证计算是否成功 */
        if (hretval != CMOX_HASH_SUCCESS)
        {
                SEGGER_RTT_printf(0, "Hash计算失败\r\n");
        }

        /* 验证哈希数值是否有28字节 */
        if (computed_size != CMOX_SHA224_SIZE)
        {
                SEGGER_RTT_printf(0, "Hash值个数和期盼的不一样多\r\n");
        }
    

    /*第4步:根据UID,签名和公钥进行验证 ================================================================*/
    /* 构建一个ECC上下文,指定数学实现方式和用于后续处理的工作缓冲区 */
    /* 注意:CMOX_ECC256_MATH_FUNCS 指的是在 cmox_default_config.h 中选择的默认数学实现。要使用特定的实现,用户可以直接选择:
       1、CMOX_MATH_FUNCS_SMALL        选择小型数学实现,主要是内存占用小
       2、CMOX_MATH_FUNCS_FAST         选择快速数学实现
       3、CMOX_MATH_FUNCS_SUPERFAST256 选择针对256位计算优化的快速数学实现
    */
    cmox_ecc_construct(&Ecc_Ctx, CMOX_ECC256_MATH_FUNCS, Working_Buffer, sizeof(Working_Buffer));

    retval = cmox_ecdsa_verify(&Ecc_Ctx,                     /* ECC上下文 */
                             CMOX_ECC_CURVE_SECP256R1,       /* 选择的SECP256R1 ECC曲线 */
                             Public_Key, sizeof(Public_Key), /* 用于验证的公钥 */
                             Computed_Hash, CMOX_SHA224_SIZE,/* 待验证的摘要 */
                             Signature, sizeof(Signature),   /* 签名数据缓冲区 */
                             &fault_check);                  /* 故障检查变量:确保在此API调用期间不会发生故障注入 */
                                                           

    /* 验证是否成功 */
    if ((retval != CMOX_ECC_AUTH_SUCCESS) && (fault_check != CMOX_ECC_AUTH_SUCCESS))
    {
        SEGGER_RTT_printf(0, "签名验证失败\r\n");
    }
    else
    {
        SEGGER_RTT_printf(0, "签名验证成功,LED2定时100ms闪烁\r\n"); 
        bsp_StartAutoTimer(0, 100);          /* 启动1个100ms的自动重装的定时器 */
    }

    /* 清除上下文 */
    cmox_ecc_cleanup(&Ecc_Ctx);

        /* 进入主程序循环体 */
        while (1)
        {
                bsp_Idle();                /* 这个函数在bsp.c文件。用户可以修改这个函数实现CPU休眠和喂狗 */

                /* 判断定时器超时时间 */
                if (bsp_CheckTimer(0))        
                {
                        bsp_LedToggle(2);        
                }

                /* 按键滤波和检测由后台systick中断服务程序实现,我们只需要调用bsp_GetKey读取键值即可。 */
                ucKeyCode = bsp_GetKey();        /* 读取键值, 无键按下时返回 KEY_NONE = 0 */
                if (ucKeyCode != KEY_NONE)
                {
                        switch (ucKeyCode)
                        {
                                case KEY_DOWN_K1:                        /* K1键按下 */

                                        break;

                                default:
                                        /* 其它的键值不处理 */
                                        break;
                        }
                }
        }
}

/***************************** 安富莱电子 [url=http://www.armfly.com]www.armfly.com[/url] (END OF FILE) *********************************/





详细说明

这个是配套TOOL脱机烧录UID签名一起使用

H7-TOOL脱机烧录的UID签名操作说明,采用ECDSA SECP256R1验证,哈希值计算使用的SHA224(2026-04-10,已经更新)
https://forum.anfulai.cn/forum.php?mod=viewthread&tid=131058

回复

使用道具 举报

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

本版积分规则

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

GMT+8, 2026-4-11 05:20 , Processed in 0.428792 second(s), 25 queries .

Powered by Discuz! X3.4 Licensed

Copyright © 2001-2023, Tencent Cloud.

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