3. 密码学基础回顾:对称加密、非对称加密与哈希函数在嵌入式中的应用
做嵌入式安全,说白了就是跟密码学打交道。你想想看,CAN升级也好,OTA远程升级也罢,核心就三件事:数据不能被偷看、数据不能被篡改、数据来源要可信。这三件事分别对应加密、完整性校验和身份认证。
我个人习惯把密码学工具分成三类:对称加密、非对称加密和哈希函数。别被这些术语吓到,咱们一个一个拆开讲。
3.1 对称加密:AES-128/256
对称加密,说白了就是加密和解密用同一把钥匙。就像你家的门锁,用钥匙锁上,再用同一把钥匙打开。在嵌入式里,最常用的就是AES。
AES 核心参数
- 密钥长度:128位、192位、256位。我建议至少用128位,资源够的话直接上256位。
- 分组大小:固定128位(16字节)。
- 工作模式:ECB、CBC、CTR、GCM等。千万别用ECB,我在项目里见过有人用ECB加密固件,结果被直接破解了。
我在项目中遇到过一件事:有个同事用AES-128加密固件,但用的是ECB模式。结果呢?攻击者通过分析密文块的重现规律,直接还原了部分固件内容。嗯,从那以后我强制团队只用CBC或GCM模式。
我的建议:OTA升级场景下,优先用AES-256-GCM。GCM模式自带认证标签,能同时保证机密性和完整性,省掉额外算哈希的步骤。
代码示例(伪代码,展示核心逻辑):
// AES-256-CBC 加密示例
uint8_t key[32] = {0x2b, 0x7e, ...}; // 256位密钥
uint8_t iv[16] = {0x00, 0x01, ...}; // 初始化向量
// 加密固件块
aes_cbc_encrypt(key, iv, plaintext, ciphertext, length);
// 解密固件块
aes_cbc_decrypt(key, iv, ciphertext, plaintext, length);
避坑指南:我曾经见过有人把IV写死在代码里。这是大忌!IV必须每次随机生成,否则攻击者可以通过IV重用破解你的加密。
3.2 非对称加密:RSA与ECC
非对称加密,加密和解密用不同的钥匙。一把公钥公开,一把私钥自己藏着。公钥加密的数据只能用私钥解密,反过来私钥签名可以用公钥验证。
在嵌入式里,非对称加密主要干两件事:数字签名和密钥交换。OTA升级里,我们用它来签名固件,确保固件是官方发布的。
| 算法 | 密钥长度 | 安全强度 | 嵌入式开销 |
|---|---|---|---|
| RSA-2048 | 2048位 | 112位等效 | 高(签名慢,验签快) |
| RSA-4096 | 4096位 | 128位等效 | 非常高 |
| ECC-256 | 256位 | 128位等效 | 低(签名快,验签快) |
| ECC-384 | 384位 | 192位等效 | 中等 |
你想想看,RSA-2048的密钥长度是2048位,而ECC-256只需要256位就能达到相同的安全强度。在资源受限的MCU上,ECC的优势非常明显。我个人习惯在STM32这类Cortex-M4/M7芯片上用ECC-256,签名验签速度能快3-5倍。
为什么ECC更适合嵌入式?
- 密钥更短,节省存储空间
- 计算更快,尤其是签名操作
- 功耗更低,适合电池供电设备
我曾经在一个项目中用RSA-2048做固件签名,结果每次签名要等好几秒,用户升级体验极差。后来换成ECC-256,签名时间降到几百毫秒,问题迎刃而解。
3.3 哈希函数:SHA-256
哈希函数,说白了就是给数据算一个「指纹」。不管数据多大,算出来的哈希值长度固定。而且,哪怕只改一个比特,哈希值都会完全不一样。
在嵌入式里,SHA-256是最常用的哈希算法。它输出256位(32字节)的哈希值,碰撞概率极低,可以放心使用。
哈希函数的三大用途
- 完整性校验:计算固件的哈希值,跟官方发布的哈希值对比,看固件有没有被篡改。
- 数字签名:先对固件算哈希,再对哈希值签名。这样签名速度快,而且能覆盖整个固件。
- 密钥派生:用HKDF(基于HMAC的密钥派生函数)从主密钥派生出多个子密钥。
代码示例:
// SHA-256 哈希计算
uint8_t hash[32];
sha256_context ctx;
sha256_init(&ctx);
sha256_update(&ctx, firmware_data, firmware_length);
sha256_final(&ctx, hash);
// 对比哈希值
if (memcmp(hash, expected_hash, 32) == 0) {
// 固件完整,可以升级
} else {
// 固件被篡改,拒绝升级
}
避坑指南:我曾经见过有人只用CRC32做固件完整性校验。CRC32是检错码,不是密码学哈希,攻击者可以轻松构造出相同CRC32的恶意固件。记住,安全场景必须用SHA-256或更强的哈希函数。
3.4 三种工具如何配合使用?
在实际的OTA升级方案中,这三种工具不是孤立使用的,而是配合起来形成一套完整的安全体系。下面这张图展示了它们的协作关系:
整个流程是这样的:
- 哈希:先对原始固件算SHA-256哈希值,得到32字节的「指纹」。
- 签名:用ECC私钥对这个哈希值签名,生成签名数据。
- 打包:把固件、签名、哈希值打包成一个升级包。
- 加密:用AES-256对整个升级包加密,防止传输过程中被窃听。
设备端收到升级包后,反向操作:先解密,再验签,最后对比哈希值。全部通过才允许升级。
为什么先哈希再签名?
直接对固件签名也可以,但固件可能很大(几MB甚至几十MB),签名算法处理大块数据很慢。先哈希再签名,签名算法只需要处理32字节的哈希值,速度快得多。而且,哈希值能代表整个固件,效果是一样的。
3.5 嵌入式环境下的选型建议
最后,我根据实际项目经验,给出一份选型建议表:
| 场景 | 推荐算法 | 理由 |
|---|---|---|
| 固件加密传输 | AES-256-GCM | 一次搞定加密+完整性校验 |
| 固件签名 | ECC-256 (secp256r1) | 密钥短、速度快、安全性高 |
| 完整性校验 | SHA-256 | 标准、稳定、硬件加速支持好 |
| 密钥交换 | ECDH (基于ECC) | 前向安全性好,适合嵌入式 |
| 随机数生成 | 硬件TRNG + DRBG | 真随机数,安全基础 |
我的经验:很多MCU(比如STM32、NXP i.MX RT系列)都内置了硬件加密引擎,支持AES、SHA、RSA、ECC等算法的硬件加速。一定要用硬件加速!纯软件实现AES-256加密1MB固件可能要几秒钟,硬件加速只需要几十毫秒。
嗯,密码学基础就讲到这里。这些工具是后面所有安全方案的地基,理解透了,后面的内容就顺了。