4、非对称加密基础:RSA算法原理、ECC算法原理、密钥对生成与管理、加密与签名区别
各位同学,欢迎来到固件签名链的第一块基石——非对称加密。说实话,我在做固件安全之前,总觉得加密算法是数学家的玩具。直到有一次,我在一个IoT设备上发现私钥被硬编码在Flash里,整个签名链形同虚设……嗯,从那以后,我深刻理解了:不懂算法原理,你就没法真正保护你的签名链。
这一章,我们不搞复杂的数学推导,而是从工程角度,把RSA、ECC、密钥管理、签名与加密的区别讲透。你想想看,固件签名链的核心就是“用私钥签名,用公钥验签”,如果连这些基础都搞混,后面的完整性验证就是空中楼阁。
4.1 RSA算法原理:大数分解的硬骨头
RSA,说白了就是“大数分解很难”这个数学事实。我刚开始接触时也觉得玄乎,其实核心就三步:选两个大素数、算乘积、找一对互逆的指数。
RSA核心流程(简化版):
- 选素数:随机选两个大素数 p 和 q(比如各1024位)
- 算模数:n = p × q,n 就是公钥和私钥都依赖的模数
- 算欧拉函数:φ(n) = (p-1)(q-1)
- 选公钥指数:选 e(常用65537),要求 1 < e < φ(n) 且 gcd(e, φ(n)) = 1
- 算私钥指数:d ≡ e⁻¹ mod φ(n),即 e×d ≡ 1 mod φ(n)
加密时:c = me mod n(m是明文,c是密文)
解密时:m = cd mod n
我在项目中遇到过一个问题:有人为了性能,把 p 和 q 选得太接近,结果被费马分解法轻松攻破。所以记住,p 和 q 的位数要差不多,但数值差距要大,这是工程上的铁律。
避坑指南:我曾经见过一个固件,RSA密钥对生成时用了弱随机数生成器,导致多个设备的 p 值相同。攻击者只要拿到两个公钥 n₁ 和 n₂,计算 gcd(n₁, n₂) 就能分解出共享的素数——整个签名链直接报废。所以,随机数质量是RSA的生命线。
4.2 ECC算法原理:椭圆曲线上的离散对数
ECC(椭圆曲线密码学)是RSA的“年轻对手”。它用更短的密钥达到同等安全强度。为什么?因为椭圆曲线上的离散对数问题比大数分解更难啃。
ECC的核心是一个椭圆曲线方程:y² = x³ + ax + b(外加一个无穷远点)。在这个曲线上,我们可以定义“点加法”:P + Q = R。然后通过重复加法实现“标量乘法”:kP = P + P + ... + P(k次)。
私钥就是一个随机大整数 k,公钥就是 kP(P是曲线上的基点)。给你公钥 kP 和基点 P,让你求 k——这就是椭圆曲线离散对数问题,目前没有多项式时间解法。
| 对比项 | RSA(2048位) | ECC(256位) |
|---|---|---|
| 安全强度 | 112位对称等价 | 128位对称等价 |
| 密钥长度 | 2048位 | 256位 |
| 签名速度 | 较慢 | 较快 |
| 验签速度 | 较快 | 较慢 |
| 典型曲线 | — | secp256r1, Curve25519 |
我个人习惯在资源受限的嵌入式设备上用ECC,因为256位的密钥比2048位的RSA密钥小得多,存储和传输都省空间。但要注意,ECC的验签比RSA慢,如果你的设备需要频繁验签(比如OTA升级时),得权衡一下。
经验之谈:在固件签名场景中,签名是一次性的(发布时签一次),验签是多次的(每个设备每次升级都要验)。所以如果验签性能是瓶颈,RSA反而有优势。我做过一个项目,用ECC验签导致启动时间多了2秒,后来切回RSA才达标。
4.3 密钥对生成与管理:从随机数到安全存储
密钥对生成,听起来简单,但坑特别多。我见过太多“生成即泄露”的案例了。
生成步骤:
- 熵源采集:从硬件随机数生成器(TRNG)或操作系统熵池获取足够熵
- 素数生成(RSA)或标量生成(ECC):用Miller-Rabin等算法验证素数性
- 密钥结构化:组装成标准格式(如PEM、DER、PKCS#8)
- 安全存储:私钥必须加密存储,公钥可以公开但需要完整性保护
密钥管理黄金法则:
- 私钥永远不离开安全硬件(HSM、TEE、SE)
- 公钥必须通过带外安全渠道分发(比如工厂预置、证书链)
- 定期轮换密钥,旧密钥要安全销毁
- 备份密钥时,用门限方案(Shamir秘密共享)拆分
我曾经在一个客户现场,发现他们把固件签名私钥放在一个共享文件夹里,权限是777。我问他们为什么,回答是“方便CI/CD流水线调用”。嗯,从那以后,我坚持所有签名操作必须在离线HSM上完成,流水线只能调用签名API,永远不能接触私钥原文。
4.4 加密与签名区别:两个完全不同的世界
这是初学者最容易混淆的地方。我面试时经常问:“RSA加密和RSA签名有什么区别?”一半人答不上来。
核心区别一句话:加密是为了保密,签名是为了认证。
| 维度 | 加密 | 签名 |
|---|---|---|
| 目的 | 防止第三方读取 | 证明发送者身份和内容完整性 |
| 使用密钥 | 公钥加密,私钥解密 | 私钥签名,公钥验签 |
| 输出 | 密文(与原文等长或略长) | 签名值(固定长度) |
| 可逆性 | 可解密还原原文 | 不可还原原文(只验证) |
| 典型场景 | 传输密钥、加密固件包 | 固件签名、代码签名 |
在固件签名链中,我们只用签名,不用加密。为什么?因为固件本身通常是公开的(或者用对称加密保护),我们真正需要的是“这个固件是谁签的”和“固件有没有被篡改”。签名正好提供这两个保证。
常见误区:有人用RSA加密代替签名,把公钥加密后的密文当签名用。这是错的!加密不提供防抵赖性,而且如果公钥公开,任何人都能解密。签名用的是私钥,只有私钥持有者才能生成有效签名,这才是固件信任链的根基。
4.5 知识体系总览
下面这张图,把本章的核心逻辑串起来了。你可以把它当作一个思维导图,每次做固件签名时,对照着检查一遍。
这张图里,RSA和ECC是两种实现非对称加密的具体算法,密钥管理是它们的“生存环境”,而加密与签名的区别决定了我们在固件场景中怎么用它们。四者缺一不可。
我的建议:刚开始学的时候,先别纠结数学细节。你只需要记住:RSA靠大数分解,ECC靠椭圆曲线离散对数;签名用私钥,验签用公钥;密钥必须安全存储。把这些工程直觉建立起来,后面学签名链就顺了。