2. 密码学基础(上)
说实话,很多做嵌入式固件开发的朋友,一听到「密码学」三个字就头大。我当年也一样,觉得这东西是数学家的玩具,跟我写C代码有什么关系?直到我第一次接手一个OTA升级项目,客户要求固件必须签名验证,否则不让跑……嗯,那段时间我恶补了不少密码学知识。
今天这节,咱们就把固件签名里最核心的几个密码学概念讲清楚。不扯太深的理论,重点是你得知道它们怎么用、为什么这么用。
对称加密 vs 非对称加密
先说说加密这件事。你想想看,你要给设备发一条指令,不想被别人偷看,怎么办?最简单的办法就是加密。
对称加密,说白了就是加密和解密用同一把钥匙。就像你家里的大门,用钥匙锁上,再用同一把钥匙打开。常见的算法有AES、DES。优点是快,特别快。我在做低功耗MCU项目时,AES-128硬件加速几乎是标配,几微秒就能加解密一个数据块。
但对称加密有个致命问题——钥匙怎么安全地交给对方?你总不能明文发过去吧?那跟没加密有啥区别?
非对称加密就解决了这个痛点。它有一对钥匙:公钥和私钥。公钥可以公开,谁都能拿到;私钥自己藏好,打死也不给别人。用公钥加密的数据,只有对应的私钥能解开。反过来,用私钥签名的数据,公钥可以验证真伪。
我习惯把非对称加密比作一个带锁的邮箱。任何人都可以把信塞进邮箱(用公钥加密),但只有邮箱主人能打开取信(用私钥解密)。
常见的非对称加密算法有RSA和ECC(椭圆曲线密码学)。RSA比较老,但生态成熟;ECC用更短的密钥达到同等安全强度,对嵌入式设备更友好。
实际项目中的选择:
- 固件加密传输:用对称加密(AES)加密固件本身,用非对称加密(RSA/ECC)加密AES密钥。这叫「混合加密」,兼顾安全性和性能。
- 固件签名验证:只用非对称加密。私钥签名,公钥验签。
哈希函数与SHA256
哈希函数是个神奇的东西。你给它一段数据,它给你一个固定长度的「指纹」。这个指纹有几个特点:
- 不可逆:从指纹推不出原始数据。你想想看,这就像把鸡蛋打成蛋花,你没法再变回一个完整的鸡蛋。
- 抗碰撞:很难找到两个不同的数据,算出相同的哈希值。
- 雪崩效应:原始数据改一个比特,哈希值就面目全非。
SHA256是SHA-2家族的一员,输出256位(32字节)的哈希值。我在项目中几乎只用SHA256,原因很简单:安全强度够用,硬件支持广泛。很多MCU都内置了SHA256硬件加速器,算一个1MB的固件,也就几百毫秒的事。
哈希函数在固件签名里扮演什么角色?
你想想看,固件可能几兆甚至几十兆,直接用非对称加密签名,效率太低了。所以实际做法是:先对固件算一个SHA256哈希值,然后只对这个32字节的哈希值做签名。验签时,同样先算固件的哈希值,再验证签名是否匹配。
避坑指南:我曾经遇到过一个坑——固件里包含了签名本身的数据。算哈希时把签名也算了进去,结果验签永远失败。后来我养成了习惯:签名数据必须从固件哈希计算中排除,或者放在固定位置,计算哈希时跳过那个区域。
数字签名原理(RSA / ECDSA)
数字签名,说白了就是给固件盖个章。这个章只有你有(私钥),但任何人都能验证(公钥)。
流程是这样的:
- 签名方(你): 计算固件的SHA256哈希值 → 用私钥对哈希值加密 → 得到签名数据 → 把签名附加到固件里。
- 验证方(设备): 收到固件 → 计算固件的SHA256哈希值 → 用公钥解密签名 → 得到原始哈希值 → 对比两个哈希值是否一致。
如果一致,说明固件确实是私钥持有者签发的,而且没有被篡改过。
RSA签名:基于大整数分解难题。密钥越长越安全,但计算也越慢。嵌入式设备上,RSA-2048是常见选择。签名操作比较慢(因为要用私钥),但验签相对快一些。
ECDSA签名:基于椭圆曲线离散对数难题。同样的安全强度下,密钥比RSA短得多。比如256位的ECDSA,安全等级相当于3072位的RSA。这对存储空间有限的嵌入式设备来说,优势很明显。
我个人更倾向ECDSA,尤其是做IoT设备时。密钥短、签名短、计算快。但要注意,ECDSA的实现比RSA复杂,容易出安全漏洞。比如随机数生成器如果不够随机,私钥就可能泄露。嗯,这里要特别小心。
重要提醒: 签名 ≠ 加密。签名用的是私钥,验证用的是公钥。加密用的是公钥,解密用的是私钥。这两个流程千万别搞混了。我见过有人把签名说成「用私钥加密」,虽然意思差不多,但容易误导新人。
知识体系总览
下面这张图,把今天讲的核心逻辑串起来了。你可以看到,固件签名和验证,本质上就是哈希函数 + 非对称加密的组合拳。
实际项目中的选择建议
| 场景 | 推荐算法 | 密钥长度 | 备注 |
|---|---|---|---|
| 资源受限MCU(如Cortex-M0) | ECDSA(P-256) | 256位 | 签名短,验签快,适合小Flash |
| 高性能处理器(如Cortex-A) | RSA-2048 或 ECDSA | 2048位 / 256位 | RSA生态好,工具链成熟 |
| 需要兼容旧设备 | RSA-2048 | 2048位 | 很多老设备只支持RSA |
| 安全等级要求极高 | ECDSA(P-384)或 RSA-4096 | 384位 / 4096位 | 计算开销大,慎用 |
我的个人习惯: 新项目一律用ECDSA P-256。密钥短、签名短、性能好。唯一要注意的是,确保随机数生成器足够安全。我曾经在一个项目里,因为硬件随机数生成器有缺陷,导致ECDSA签名时重复使用了随机数,结果私钥被算出来了……那真是血的教训。
好了,这一节的内容就到这儿。密码学基础是固件签名的地基,地基不稳,上面盖的房子再漂亮也没用。下一节咱们会深入具体的签名工具链和命令行操作,到时候手把手带你走一遍完整的签名流程。
可可精品资料库