# Hash算法 ***Copyright © Quectel Wireless Solutions Co., Ltd. 2026. All rights reserved.*** --- # 功能概述 本模块提供标准的消息摘要(Hash)计算功能,支持SHA-1、SHA-256和MD5算法,可用于数据完整性校验、密码加盐散列存储,以及基于HMAC(散列消息认证码)的API鉴权防篡改。 ## 主要应用场景 1. 文件完整性校验:下载OTA固件后计算其SHA-256摘要,与云端提供的摘要比对,判断文件是否损坏或被篡改。 2. 报文完整性校验:对通信数据计算Hash值,确认传输前后内容一致。 3. HMAC身份认证:使用密钥对消息计算HMAC-SHA256签名,供云端与设备双方校验请求是否合法。 4. 密码保护:不直接保存明文密码,而是保存经专用密码哈希算法处理后的结果;嵌入式设备常用PBKDF2-HMAC-SHA256。 5. 密钥派生:通过ECDH得到共享秘密后,使用HKDF-SHA256派生AES会话密钥。 6. 数字签名:RSA/ECDSA通常先对固件或数据计算SHA-256摘要,再对摘要进行签名。 7. 数据去重与版本识别:通过比较文件的Hash值判断两个文件内容是否相同。 ## 常见问题 1. Hash不是加密算法:Hash运算不可逆,无法"解密",主要用于完整性校验和摘要计算。 2. 密码不能直接用SHA-256存储:保存密码应使用Argon2、bcrypt、scrypt或PBKDF2等专用算法,并加入随机盐。 3. 身份认证不能只用普通Hash:消息防篡改应使用HMAC-SHA256,不能以"密钥拼接数据后直接计算SHA-256"的方式代替。 4. 避免使用MD5/SHA-1:安全场景应优先选用SHA-256/SHA-3;比较摘要时应使用恒定时间比较,避免时序信息泄露。 # Hash算法 API ## 头文件 *qcm_sha256.h* ## 函数概览 | **函数** | **说明** | | --- | --- | | *qcm_core_sha256()* | 一次性计算输入数据的SHA-256摘要 | | *qcm_hmac_sha256()* | 一次性计算数据的HMAC-SHA256认证码 | | *qcm_sha256_init()* | 初始化SHA-256流式计算上下文 | | *qcm_sha256_starts()* | 启动或重置流式计算 | | *qcm_sha256_update()* | 追加处理一段输入数据 | | *qcm_sha256_finish()* | 结束流式计算并输出32字节摘要 | | *qcm_sha256_free()* | 释放SHA-256上下文并清除敏感数据 | ## 函数详解 ### qcm_core_sha256 - **功能描述** 一次性计算输入数据的SHA-256摘要。适用于长度较小且已知的数据,将任意长度的输入直接散列为32字节的摘要结果。系统同时提供宏别名 *qcm_sha256()*,两者功能完全一致。 - **函数原型** ```c void qcm_core_sha256(const qosa_uint8_t *input, qosa_uint32_t ilen, qosa_uint8_t output[32]); ``` - **参数说明** | **参数名** | **输入/输出** | **类型** | **说明** | | --- | --- | --- | --- | | *input* | 输入 | const qosa_uint8_t * | 待计算数据的缓冲区首地址 | | *ilen* | 输入 | qosa_uint32_t | 输入数据的长度;单位:字节 | | *output* | 输出 | qosa_uint8_t[32] | 存放32字节摘要结果的输出数组 | - **返回值说明** 无 ### qcm_hmac_sha256 - **功能描述** 基于SHA-256计算HMAC(密钥散列消息认证码)。常用于调用云平台API时,对密钥与请求报文联合运算生成鉴权签名,防止请求内容被篡改。 - **函数原型** ```c void qcm_hmac_sha256(const qosa_uint8_t *msg, qosa_uint32_t msg_len, const qosa_uint8_t *key, qosa_uint32_t key_len, qosa_uint8_t output[32]); ``` - **参数说明** | **参数名** | **输入/输出** | **类型** | **说明** | | --- | --- | --- | --- | | *msg* | 输入 | const qosa_uint8_t * | 待认证消息的缓冲区首地址 | | *msg_len* | 输入 | qosa_uint32_t | 消息长度;单位:字节 | | *key* | 输入 | const qosa_uint8_t * | 鉴权密钥的缓冲区首地址 | | *key_len* | 输入 | qosa_uint32_t | 密钥长度;单位:字节 | | *output* | 输出 | qosa_uint8_t[32] | 存放32字节认证码结果的输出数组 | - **返回值说明** 无 ### qcm_sha256_init - **功能描述** 初始化SHA-256流式计算上下文,为流式计算做准备。流式计算流程的第一步。 - **函数原型** ```c void qcm_sha256_init(qcm_core_sha256_context_t *ctx); ``` - **参数说明** | **参数名** | **输入/输出** | **类型** | **说明** | | --- | --- | --- | --- | | *ctx* | 输出 | *qcm_core_sha256_context_t ** | 待初始化的上下文;详见 [*qcm_core_sha256_context_t*](#qcmcoresha256contextt) | - **返回值说明** 无 ### qcm_sha256_starts - **功能描述** 启动或重置流式计算。若上下文中存有此前的计算状态,将被重置。 - **函数原型** ```c void qcm_sha256_starts(qcm_core_sha256_context_t *ctx); ``` - **参数说明** | **参数名** | **输入/输出** | **类型** | **说明** | | --- | --- | --- | --- | | *ctx* | 输入/输出 | *qcm_core_sha256_context_t ** | 已初始化的上下文;详见 [*qcm_core_sha256_context_t*](#qcmcoresha256contextt) | - **返回值说明** 无 ### qcm_sha256_update - **功能描述** 追加处理一段输入数据。可循环多次调用,将超出内存容量的大文件分段送入计算。 - **函数原型** ```c void qcm_sha256_update(qcm_core_sha256_context_t *ctx, const qosa_uint8_t *input, qosa_uint32_t ilen); ``` - **参数说明** | **参数名** | **输入/输出** | **类型** | **说明** | | --- | --- | --- | --- | | *ctx* | 输入/输出 | *qcm_core_sha256_context_t ** | 已完成启动的上下文;详见 [*qcm_core_sha256_context_t*](#qcmcoresha256contextt) | | *input* | 输入 | const qosa_uint8_t * | 本次追加数据的缓冲区首地址 | | *ilen* | 输入 | qosa_uint32_t | 本次追加数据的长度;单位:字节 | - **返回值说明** 无 ### qcm_sha256_finish - **功能描述** 结束流式计算,输出最终的32字节摘要,内部自动完成数据补位。 - **函数原型** ```c void qcm_sha256_finish(qcm_core_sha256_context_t *ctx, qosa_uint8_t output[32]); ``` - **参数说明** | **参数名** | **输入/输出** | **类型** | **说明** | | --- | --- | --- | --- | | *ctx* | 输入/输出 | *qcm_core_sha256_context_t ** | 当前计算的上下文;详见 [*qcm_core_sha256_context_t*](#qcmcoresha256contextt) | | *output* | 输出 | qosa_uint8_t[32] | 存放32字节摘要结果的输出数组 | - **返回值说明** 无 ### qcm_sha256_free - **功能描述** 释放SHA-256上下文,擦除其中的内部状态与敏感数据,防止残留数据被误用。 - **函数原型** ```c void qcm_sha256_free(qcm_core_sha256_context_t *ctx); ``` - **参数说明** | **参数名** | **输入/输出** | **类型** | **说明** | | --- | --- | --- | --- | | *ctx* | 输入/输出 | *qcm_core_sha256_context_t ** | 计算完成后待清理的上下文;详见 [*qcm_core_sha256_context_t*](#qcmcoresha256contextt) | - **返回值说明** 无 ## 结构体定义 ### qcm_core_sha256_context_t SHA-256流式计算上下文结构体定义如下: ```c typedef struct { qosa_uint32_t total[2]; qosa_uint32_t state[8]; qosa_uint8_t buffer[64]; qosa_uint8_t is224; } qcm_core_sha256_context_t; ``` | **参数** | **类型** | **说明** | | --- | --- | --- | | *total* | qosa_uint32_t[2] | 已处理数据的总长度计数器;单位:字节 | | *state* | qosa_uint32_t[8] | 哈希运算的中间状态 | | *buffer* | qosa_uint8_t[64] | 暂存不足64字节的末尾数据,供后续运算或结束时补位处理 | | *is224* | qosa_uint8_t | 算法选择标志
*0*:SHA-256
其他值:SHA-224 | # 应用逻辑流程图 ```{image} images/image_MehQb5OlBo2b01xPXo9cvTCjn5g.webp :width: 1038px :height: 733px ``` # 示例代码 1. 常规短文本摘要计算(一次性计算): ```c #include "qcm_sha256.h" #include "qosa_sys.h" void app_sha_demo_short() { qosa_uint8_t input_msg[] = "Hello_UniRTOS_2026!"; qosa_uint8_t hash_res[32] = {0}; // 一次性计算,调用完成后 hash_res 中即为32字节摘要结果 qcm_core_sha256(input_msg, sizeof(input_msg) - 1, hash_res); } ``` 2. 大文件分段计算(流式计算): ```c #include "qcm_sha256.h" #include "qosa_sys.h" void app_sha_demo_long_file_sim() { qcm_core_sha256_context_t ctx; qosa_uint8_t final_res[32] = {0}; qosa_uint8_t file_chunk_buf[1024]; // 每次读取1024字节的数据缓冲区 // 1. 初始化并启动流式计算 qcm_sha256_init(&ctx); qcm_sha256_starts(&ctx); // 2. 循环读取文件并分段送入计算 while(/* 文件未读完,每次读取一段数据存入 file_chunk_buf */) { qcm_sha256_update(&ctx, file_chunk_buf, 1024 /* 实际读取长度 */); } // 3. 结束计算并获取最终摘要 qcm_sha256_finish(&ctx, final_res); // 4. 释放上下文 qcm_sha256_free(&ctx); } ```