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(),两者功能完全一致。

  • 函数原型

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时,对密钥与请求报文联合运算生成鉴权签名,防止请求内容被篡改。

  • 函数原型

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流式计算上下文,为流式计算做准备。流式计算流程的第一步。

  • 函数原型

void qcm_sha256_init(qcm_core_sha256_context_t *ctx);
  • 参数说明

参数名

输入/输出

类型

说明

ctx

输出

*qcm_core_sha256_context_t **

待初始化的上下文;详见 qcm_core_sha256_context_t

  • 返回值说明

qcm_sha256_starts

  • 功能描述
    启动或重置流式计算。若上下文中存有此前的计算状态,将被重置。

  • 函数原型

void qcm_sha256_starts(qcm_core_sha256_context_t *ctx);
  • 参数说明

参数名

输入/输出

类型

说明

ctx

输入/输出

*qcm_core_sha256_context_t **

已初始化的上下文;详见 qcm_core_sha256_context_t

  • 返回值说明

qcm_sha256_update

  • 功能描述
    追加处理一段输入数据。可循环多次调用,将超出内存容量的大文件分段送入计算。

  • 函数原型

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

input

输入

const qosa_uint8_t *

本次追加数据的缓冲区首地址

ilen

输入

qosa_uint32_t

本次追加数据的长度;单位:字节

  • 返回值说明

qcm_sha256_finish

  • 功能描述
    结束流式计算,输出最终的32字节摘要,内部自动完成数据补位。

  • 函数原型

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

output

输出

qosa_uint8_t[32]

存放32字节摘要结果的输出数组

  • 返回值说明

qcm_sha256_free

  • 功能描述
    释放SHA-256上下文,擦除其中的内部状态与敏感数据,防止残留数据被误用。

  • 函数原型

void qcm_sha256_free(qcm_core_sha256_context_t *ctx);
  • 参数说明

参数名

输入/输出

类型

说明

ctx

输入/输出

*qcm_core_sha256_context_t **

计算完成后待清理的上下文;详见 qcm_core_sha256_context_t

  • 返回值说明

结构体定义

qcm_core_sha256_context_t

SHA-256流式计算上下文结构体定义如下:

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

应用逻辑流程图

../../../_images/image_MehQb5OlBo2b01xPXo9cvTCjn5g.webp

示例代码

  1. 常规短文本摘要计算(一次性计算):

#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);
}
  1. 大文件分段计算(流式计算):

#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);
}