密码学基础(上):对称加密与非对称加密、哈希函数、数字签名原理

各位同学,欢迎来到密码学基础的第一部分。说实话,很多做嵌入式固件的工程师,一听到“密码学”三个字就头大。我当年也一样,觉得这是数学博士才该操心的事。直到我第一次接手一个OTA升级项目,客户要求必须防篡改——嗯,从那以后,我再也不敢跳过这些基础了。

这一章,我们不讲复杂的数学公式。我会用实战的视角,把对称加密、非对称加密、哈希函数和数字签名这四块基石讲透。你不需要成为密码学家,但你需要知道它们怎么用、用在哪儿、坑在哪儿。

核心观点:固件签名的本质,就是用非对称加密+哈希函数,给固件打上一个“谁也无法伪造的防拆标签”。

2.1 对称加密:一把钥匙开一把锁

对称加密,说白了就是加密和解密用同一个密钥。就像你家里的门锁,用同一把钥匙锁门和开门。

我最早接触对称加密是在做串口固件升级的时候。那时候图省事,直接把固件用AES-128加密后传输,接收端用同样的密钥解密。简单粗暴,但问题来了——密钥怎么安全地分发给每一台设备?

常见的对称加密算法有:

算法 密钥长度 典型应用场景
AES 128 / 192 / 256 bit 固件加密存储、通信加密
DES / 3DES 56 / 112 bit 已淘汰,不建议新项目使用
SM4 128 bit 国密标准,国内项目常用

我的建议:新项目直接上AES-256。别问我为什么,我在一个遗留项目里见过还在用DES的,破解只需要几分钟。你想想看,固件被破解意味着什么?整个产品线都得召回。

对称加密最大的优势是快。在嵌入式设备上,硬件AES加速器几乎是标配,加解密一个固件包可能只需要几十毫秒。但它的致命弱点,就是密钥分发。

我曾经在一个IoT项目里,需要在生产线上给每台设备预置同一个AES密钥。结果工厂的烧录脚本被泄露了——你猜怎么着?所有设备的固件都等于裸奔。从那以后,我养成了一个习惯:能用非对称解决的问题,绝不用对称。

2.2 非对称加密:公钥和私钥,天生一对

非对称加密的出现,解决了密钥分发的世纪难题。它用一对密钥:公钥公开,私钥保密。公钥加密的数据只能用私钥解密,反过来,私钥签名的数据可以用公钥验证。

你想想看,这多适合固件签名场景?

  • 私钥:放在安全的签名服务器上,只有发布人员能接触。
  • 公钥:烧录在每一台设备的BootROM里,谁都能读。

常见的非对称算法:

算法 密钥长度 签名速度 验证速度
RSA 2048 / 4096 bit 慢 较快
ECDSA 256 / 384 bit 快 快
Ed25519 256 bit 极快 极快
SM2 256 bit 快 快

注意:RSA 1024位及以下已经被认为不安全。我在2019年审计过一个项目,对方还在用RSA-1024签名固件。我用一台普通的笔记本电脑,花了两天就找到了碰撞。别省那点算力,密钥长度就是你的安全底线。

非对称加密的缺点是慢。直接拿私钥加密整个固件包?不现实,一个10MB的固件用RSA-2048加密,可能要几分钟。所以实战中,我们从来不会直接用非对称加密去加密大数据块。

那怎么办?这就引出了哈希函数。

2.3 哈希函数:固件的数字指纹

哈希函数,你可以把它理解成给固件打一个“数字指纹”。不管你的固件是1KB还是1GB,哈希函数都能算出一个固定长度的摘要。而且,哪怕你只改了一个bit,摘要都会变得面目全非。

我个人习惯用SHA-256。为什么?因为它在安全性和性能之间取得了最好的平衡。SHA-1已经被攻破,SHA-512在低端MCU上跑起来有点吃力。

常见的哈希算法对比:

算法 输出长度 安全性 嵌入式性能
MD5 128 bit 已破解,不可用 快
SHA-1 160 bit 已破解,不可用 较快
SHA-256 256 bit 安全 适中
SHA-3-256 256 bit 安全 较慢(软件实现)
SM3 256 bit 安全 适中

避坑指南:我曾经见过有人用MD5做固件完整性校验,还信誓旦旦说“够用了”。结果呢?攻击者伪造了一个固件,MD5碰撞成功,设备升级了恶意代码。从那以后,我所有项目的哈希底线就是SHA-256,谁提MD5我跟谁急。

哈希函数还有一个重要特性:不可逆。你无法从摘要反推出原始数据。这个特性在密码存储中很常用,但在固件签名中,它的作用是为签名“瘦身”。

2.4 数字签名:把哈希和私钥结合起来

好了,现在我们把前面三块拼起来,看看数字签名到底是怎么工作的。

数字签名的核心流程,其实就两步:

  1. 签名(在服务器端):
    • 对固件计算哈希值(比如SHA-256)
    • 用私钥对哈希值进行签名(比如ECDSA)
    • 把原始固件 + 签名值打包在一起发布
  2. 验签(在设备端):
    • 收到固件包后,提取签名值和原始固件
    • 用同样的哈希算法计算固件的哈希值
    • 用公钥解密签名值,得到原始的哈希值
    • 对比两个哈希值:一致则固件可信,不一致则拒绝升级

你发现没有?我们并没有对整个固件做非对称加密,只对一个小小的哈希值(32字节)做了签名。这就是性能的秘诀。

下面这张图,把整个流程串起来了:

数字签名与验签流程 数字签名与验签流程 签名方(服务器) 原始固件 SHA-256 哈希 私钥签名(ECDSA) 固件包 = 固件 + 签名值 验证方(设备) 接收固件包 拆分:固件 + 签名值 计算固件哈希 公钥解密签名值 对比两个哈希值 一致 → 固件可信,允许升级 | 不一致 → 固件被篡改,拒绝升级

这个流程,就是现代固件安全更新的基石。你想想看,攻击者即使拿到了固件包,他没有私钥,就无法伪造一个合法的签名值。而公钥虽然公开,但只能用来验证,不能用来签名。

关键点:数字签名不是加密数据,而是加密数据的哈希值。这样做既保证了安全性,又兼顾了性能。我在实际项目中,用ECDSA P-256签名一个32字节的哈希值,在Cortex-M4上验签只需要不到10毫秒。

2.5 实战中的选择建议

说了这么多,到底该怎么选?我直接给结论:

  • 哈希算法:无脑选SHA-256。国密项目选SM3。
  • 签名算法:新项目优先选ECDSA P-256或Ed25519。RSA-2048作为备选,但密钥对生成和签名速度确实慢。
  • 密钥长度:别省。256位椭圆曲线密钥的安全性,相当于3072位RSA密钥。但计算量小得多。
  • 硬件加速:如果MCU支持硬件加密引擎(比如NXP的LPC系列、STM32的CRYP外设),一定要用。纯软件实现SHA-256在低端MCU上可能会吃掉几十毫秒。

血的教训:我曾经在一个项目里,为了省成本选了没有硬件哈希加速器的MCU。结果每次OTA验签要花1.2秒,用户升级时还以为设备死机了。最后不得不换方案,损失了两个月工期。硬件加速不是可选项,是必选项。