密码学基础(上):对称加密与非对称加密、哈希函数(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;
}
数字签名:防篡改的核心武器
数字签名结合了哈希函数和非对称加密。它解决三个问题:
- 完整性:固件有没有被篡改?
- 真实性:固件是不是来自声称的发布者?
- 不可否认性:发布者不能抵赖自己签发的固件
签名流程其实很简单:
- 发布者计算固件的 SHA-256 哈希值
- 用私钥对哈希值加密,得到签名
- 将固件和签名一起发布
- 验证者用公钥解密签名,得到原始哈希
- 重新计算固件哈希,对比两者是否一致
关键点: 签名验证的是哈希值,不是整个固件。这样既保证了安全性,又大幅提升了验证速度。我在项目中实测过,SHA-256 加 RSA 2048 签名验证,在 200MHz 的 Cortex-M4 上只需不到 100 毫秒。
知识体系总览
下面这张图把本章的核心逻辑串起来了。你看一遍,应该能对密码学基础有个整体把握。
实际项目中的选择建议
做固件签名验证时,我一般这样选型:
- 哈希算法:SHA-256,没有之一。SHA-1 已被证明不安全,SHA-512 在嵌入式平台开销太大
- 签名算法:资源受限的 MCU 用 ECDSA(P-256 曲线),性能强的 SoC 可以用 RSA 2048
- 密钥长度:不低于 256 位(ECC)或 2048 位(RSA)
一个小技巧: 在固件头部预留签名验证结果标志位。Bootloader 先检查这个标志,如果上次验证通过且固件未更新,可以跳过重复验证,大幅缩短启动时间。我在某款车规级 MCU 上这么做过,启动时间从 800ms 降到了 120ms。
嗯,密码学基础就讲到这里。这些概念是后续所有防篡改技术的根基。你理解了对称与非对称的区别,掌握了哈希的用途,明白了数字签名怎么组合这些原语,后面讲固件签名流程时就会轻松很多。