4. 核心算法:RSA 算法原理与 ECC 简介

聊到嵌入式签名验签,绕不开 RSA。这玩意儿虽然年纪不小了,但至今仍是工业界的扛把子。我个人习惯把 RSA 比作一个「单向门」——从这边过去容易,想从那边翻回来?门儿都没有。

咱们先把这个门的结构拆开看。你理解了密钥生成、加解密、签名验签这三块,基本就能应付 90% 的嵌入式场景了。

4.1 RSA 密钥生成:找两个大质数

RSA 的安全性,说白了就建立在「大数分解很难」这个数学事实上。我当年刚入行时,总觉得这步很简单,直到有一次在资源受限的 MCU 上生成 2048 位密钥……嗯,那感觉就像用计算器算圆周率,慢得让人怀疑人生。

密钥生成的步骤其实很固定:

  1. 选两个大质数 p 和 q。实际中通常用 512 位以上,乘积 n = p × q 就是密钥长度(比如 1024 位、2048 位)。
  2. 计算欧拉函数 φ(n) = (p-1)(q-1)。这一步是数学核心,但代码里就是个乘法。
  3. 选一个公钥指数 e。常用 65537(0x10001),为什么?因为它二进制只有两个 1,模幂运算快。
  4. 计算私钥 d,满足 e × d ≡ 1 (mod φ(n))。说白了就是求 e 的模逆元。

关键点:p 和 q 必须随机生成,且不能太接近。我在项目中见过有人直接用固定质数表,结果被侧信道攻击一把梭——千万别偷懒。

生成完,公钥就是 (n, e),私钥是 (n, d)。p、q、φ(n) 这些中间值,用完最好立刻擦掉。嵌入式环境里,内存残留是安全大忌。

4.2 RSA 加密与解密:数学魔术

加密和解密,其实就是两个模幂运算:

  • 加密:密文 c = m^e mod n(m 是明文,必须小于 n)
  • 解密:明文 m = c^d mod n

你想想看,为什么能还原?因为 e 和 d 互为逆元,模幂运算的交换律保证了 m^(e×d) ≡ m (mod n)。

但这里有个坑——直接对数据做 RSA 加密是不安全的。为什么?因为 RSA 是确定性算法,同样的明文每次加密结果都一样。攻击者可以搞字典攻击。

避坑指南:我曾经在一个 IoT 设备固件升级方案里,看到有人直接用 RSA 加密固件块。结果每个块的前几个字节固定(文件头),攻击者直接通过密文比对就猜出了固件版本。正确的做法是使用 OAEP 或 PKCS#1 v1.5 填充。

嵌入式里,RSA 加密用得少,签名才是主流。因为公钥加密太慢,通常只用来加密对称密钥(比如 AES 密钥),这叫「混合加密」。

4.3 RSA 签名与验签:反过来用

签名验签,其实就是把加解密反过来:

  • 签名:用私钥 d 对哈希值做模幂运算,生成签名 s = hash(m)^d mod n
  • 验签:用公钥 e 对签名做模幂运算,得到 hash' = s^e mod n,然后比对 hash' 和原始哈希

为什么能验?因为只有私钥持有者能生成合法的 s,而公钥任何人都能验证。这就是「不可否认性」的来源。

实际工程中,签名流程是这样的:

// 伪代码:RSA 签名流程
1. 计算消息哈希:h = SHA256(message)
2. 对哈希做 DER 编码(填充算法标识)
3. 做 PKCS#1 v1.5 或 PSS 填充
4. 模幂运算:signature = padded_hash^d mod n
5. 输出签名(通常和消息一起发送)

// 验签流程
1. 从消息计算哈希:h = SHA256(message)
2. 模幂运算:padded_hash' = signature^e mod n
3. 解填充,提取哈希值
4. 比对 h 和提取出的哈希值

我的经验:填充方案选 PSS 更安全,但 PKCS#1 v1.5 兼容性更好。如果设备要跟云端通信,先确认对方支持哪种。我曾经因为填充不匹配,调了三天接口……

4.4 RSA 在嵌入式中的性能考量

RSA 的运算量主要在模幂上。2048 位 RSA 签名,在 Cortex-M4 上大概需要几百毫秒到几秒。这个速度够不够?看场景:

场景 RSA 操作 典型耗时(Cortex-M4 @ 100MHz) 是否可接受
固件启动验签 验签一次 200-500ms ✅ 可以(启动一次)
OTA 包签名 签名一次 1-3s ✅ 可以(后台操作)
每包数据签名 频繁签名 秒级 ❌ 不行(换 ECC 或 HMAC)

如果 MCU 没有硬件加速器,RSA 的模幂运算就是纯软件算。我建议:能上硬件加速就上,比如 NXP 的 i.MX RT 系列自带 RSA 引擎,速度能快 10 倍以上。

4.5 ECC 算法简介:小而美

ECC(椭圆曲线密码学)是 RSA 的替代者。它用更短的密钥达到同等安全强度:

安全等级 RSA 密钥长度 ECC 密钥长度 优势
80 位 1024 160-223 ECC 短 5-6 倍
112 位 2048 224-255 ECC 短 8 倍
128 位 3072 256-383 ECC 短 10 倍
256 位 15360 512+ ECC 短 30 倍

为什么 ECC 这么强?因为它基于「椭圆曲线离散对数问题」——比大数分解难得多。说白了,同样的破解算力,ECC 能扛更久。

ECC 的核心操作是标量乘法:k × G,其中 G 是曲线上的基点,k 是私钥。这个运算比 RSA 的模幂快不少,尤其适合资源受限的嵌入式设备。

实际选型建议:

  • 如果设备有硬件加速器,RSA 2048 仍然够用,生态成熟
  • 如果追求性能或密钥存储空间有限,选 ECC P-256(secp256r1)
  • 如果考虑量子安全,RSA 和 ECC 都不行,得换后量子密码(但那是另一门课了)

4.6 RSA vs ECC:一张图看懂

下面这张图,是我自己画的核心逻辑对比。你一看就明白两者的定位差异:

RSA vs ECC 核心对比 RSA 基于大数分解 密钥长(2048+ 位) 运算慢(模幂) 生态最成熟 适合:启动验签、OTA ECC 基于椭圆曲线离散对数 密钥短(256 位) 运算快(标量乘) 生态逐渐成熟 适合:频繁签名、小内存设备 共同点 都是非对称密码,都用于签名/密钥交换 都需要安全随机数生成器,都怕侧信道攻击 选型建议 有硬件加速 → RSA 2048 够用 资源受限 → ECC P-256 更优

4.7 嵌入式签名验签的工程要点

最后,我总结几个实际项目里踩过的坑:

  • 随机数生成器:RSA 和 ECC 都依赖高质量随机数。嵌入式里别用 rand(),用硬件 TRNG 或 DRBG。我曾经见过用系统 tick 做种子的……那安全性约等于零。
  • 侧信道防护:模幂运算的时间、功耗、电磁辐射都可能泄露密钥。加「盲化」或「恒定时间」实现,别裸奔。
  • 密钥存储:私钥别明文放 Flash。用安全元件(SE)或 TEE 保护。如果 MCU 没有这些,至少做 XOR 混淆或烧断熔丝。
  • 证书链:别只验根证书。中间证书也要验,否则攻击者可以伪造子证书。我在一个网关项目里就因为这个被攻破过……

一句话总结:RSA 是老兵,可靠但笨重;ECC 是新锐,灵活但要注意曲线选择。嵌入式里,选哪个取决于你的硬件资源、性能需求和生态兼容性。没有银弹,只有权衡。