密码学基础(上):对称加密与非对称加密、哈希函数(SHA-256)、数字签名原理

做固件安全,绕不开密码学。很多人觉得密码学是数学家的活儿,离工程很远。其实不然。你想想看,签名验证的每一环——加密、哈希、签名——背后都是这些基础概念在撑腰。我刚开始接触嵌入式安全时,也踩过不少坑,今天就把这些核心知识点掰开了讲清楚。

对称加密:一把钥匙开一把锁

对称加密,说白了就是加密和解密用同一把密钥。就像你家里的门锁,用同一把钥匙锁门、开门。

常见的对称加密算法有 AES、DES、SM4。AES 是目前最主流的,密钥长度支持 128、192、256 位。我个人习惯在固件加密场景中优先选 AES-128,性能和安全性平衡得最好。

核心流程:

  • 发送方用密钥 K 加密明文 P,得到密文 C
  • 接收方用同一密钥 K 解密密文 C,恢复明文 P

对称加密最大的优势是快。硬件加速后,AES 加密一个 16 字节块只需要几十个时钟周期。但问题也很明显——密钥怎么安全地传给对方?

我曾经踩过的坑: 早期做 OTA 升级包加密时,直接把 AES 密钥硬编码在固件里。结果攻击者通过反编译轻松拿到了密钥,整个加密形同虚设。记住:密钥管理比加密算法本身更重要。

非对称加密:公钥私钥,各司其职

非对称加密解决了密钥分发难题。它使用一对密钥:公钥公开,私钥保密。公钥加密的数据只能用私钥解密,私钥加密的数据只能用公钥解密。

常见的算法有 RSA、ECC(椭圆曲线密码)。RSA 基于大整数分解难题,ECC 基于椭圆曲线离散对数问题。同等安全强度下,ECC 的密钥更短、计算更快。

算法 密钥长度(位) 安全强度 典型应用
RSA 2048 112 位 数字签名、密钥交换
ECC 256 128 位 嵌入式签名、TLS
SM2 256 128 位 国密标准

非对称加密的缺点是慢。RSA 2048 签名一次大约需要几毫秒,而 AES 加密同样数据只需微秒级。所以在实际固件签名中,我们通常混合使用:用非对称加密保护对称密钥,用对称加密加密固件本体。

哈希函数:数据的数字指纹

哈希函数能把任意长度的数据,压缩成固定长度的摘要。而且这个摘要是唯一的——哪怕只改一个比特,摘要也会面目全非。

SHA-256 是当前最常用的哈希算法,输出 256 位(32 字节)的摘要。它的特点是:

  • 单向性:从摘要反推原始数据,计算上不可行
  • 抗碰撞性:找到两个不同数据产生相同摘要,极其困难
  • 雪崩效应:输入微小变化,输出剧烈变化

我建议: 在固件完整性校验中,先用 SHA-256 计算固件哈希,再对哈希值做签名。这样既保证了完整性,又避免了直接对大数据量做非对称加密的性能开销。

来看一段 C 语言调用 OpenSSL 计算 SHA-256 的示例:

#include <openssl/sha.h>
#include <stdio.h>
#include <string.h>

void calc_sha256(const unsigned char *data, size_t len, unsigned char *out) {
    SHA256_CTX ctx;
    SHA256_Init(&ctx);
    SHA256_Update(&ctx, data, len);
    SHA256_Final(out, &ctx);
}

int main() {
    unsigned char data[] = "Hello, firmware!";
    unsigned char hash[SHA256_DIGEST_LENGTH];
    
    calc_sha256(data, strlen((char*)data), hash);
    
    printf("SHA-256: ");
    for(int i = 0; i < SHA256_DIGEST_LENGTH; i++) {
        printf("%02x", hash[i]);
    }
    printf("\n");
    return 0;
}

数字签名:防篡改的核心武器

数字签名结合了哈希函数和非对称加密。它解决三个问题:

  • 完整性:固件有没有被篡改?
  • 真实性:固件是不是来自声称的发布者?
  • 不可否认性:发布者不能抵赖自己签发的固件

签名流程其实很简单:

  1. 发布者计算固件的 SHA-256 哈希值
  2. 用私钥对哈希值加密,得到签名
  3. 将固件和签名一起发布
  4. 验证者用公钥解密签名,得到原始哈希
  5. 重新计算固件哈希,对比两者是否一致

关键点: 签名验证的是哈希值,不是整个固件。这样既保证了安全性,又大幅提升了验证速度。我在项目中实测过,SHA-256 加 RSA 2048 签名验证,在 200MHz 的 Cortex-M4 上只需不到 100 毫秒。

知识体系总览

下面这张图把本章的核心逻辑串起来了。你看一遍,应该能对密码学基础有个整体把握。

密码学基础核心逻辑 对称加密 非对称加密 哈希函数 SHA-256 特性 速度快 密钥分发困难 适合加密大数据 特性 速度慢 密钥分发安全 适合签名/密钥交换 特性 单向性 抗碰撞性 雪崩效应 数字签名 = 哈希 + 非对称加密 实际固件签名流程:SHA-256 计算哈希 → 私钥签名哈希 → 公钥验证签名 既保证完整性,又保证真实性,还解决了密钥分发问题

实际项目中的选择建议

做固件签名验证时,我一般这样选型:

  • 哈希算法:SHA-256,没有之一。SHA-1 已被证明不安全,SHA-512 在嵌入式平台开销太大
  • 签名算法:资源受限的 MCU 用 ECDSA(P-256 曲线),性能强的 SoC 可以用 RSA 2048
  • 密钥长度:不低于 256 位(ECC)或 2048 位(RSA)

一个小技巧: 在固件头部预留签名验证结果标志位。Bootloader 先检查这个标志,如果上次验证通过且固件未更新,可以跳过重复验证,大幅缩短启动时间。我在某款车规级 MCU 上这么做过,启动时间从 800ms 降到了 120ms。

嗯,密码学基础就讲到这里。这些概念是后续所有防篡改技术的根基。你理解了对称与非对称的区别,掌握了哈希的用途,明白了数字签名怎么组合这些原语,后面讲固件签名流程时就会轻松很多。