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

各位同学,欢迎来到《Bootloader安全启动与签名验证实战》的第二讲。今天咱们聊聊密码学基础,这是整个安全启动体系的“地基”。

说实话,我早年做嵌入式开发时,对密码学也是“敬而远之”。总觉得那是数学家的活儿,我们搞硬件的,把功能跑通就行了。直到有一次,我负责的一个IoT产品被爆出固件被逆向、篡改,客户数据泄露……那段时间真是焦头烂额。从那以后,我深刻意识到:不懂密码学的嵌入式工程师,就像不带盾牌上战场的士兵。

好,废话不多说。今天这堂课,我会把对称加密、非对称加密、哈希函数和数字签名这几个核心概念,用咱们工程师能听懂的方式讲清楚。你不需要成为密码学专家,但听完后,你至少能明白Bootloader里那些签名校验代码到底在干什么。

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

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

常见的对称加密算法有:AES、DES、3DES、SM4(国密)等。在嵌入式领域,AES(高级加密标准)是绝对的主流。为什么?因为它速度快、硬件支持好、安全性也够用。

我个人的习惯是,在Bootloader里做固件加密存储时,优先选用AES-128-CBC模式。128位密钥在安全性和性能之间取得了很好的平衡。256位当然更安全,但计算开销也更大,对于资源受限的MCU来说,有时候得不偿失。

核心要点:对称加密的优点是速度快,适合加密大量数据。缺点是密钥分发困难——你想想看,如果每个设备里都预置同一个密钥,一旦某个设备被攻破,整个产品线的密钥就都暴露了。

我在项目中遇到过这样一个坑:有同事为了省事,把AES密钥直接硬编码在固件里,而且没有做任何混淆。结果呢?逆向工程师用IDA Pro一搜,直接找到了密钥常量。嗯,那款产品的安全防护形同虚设。所以,密钥的存储和管理,是嵌入式安全里最容易被忽视、也最致命的一环。

二、非对称加密:公钥和私钥,一对好搭档

非对称加密就高级一些了。它使用一对密钥:公钥(Public Key)私钥(Private Key)。公钥可以公开,私钥必须保密。

它的核心思想是:用公钥加密,只能用私钥解密;用私钥签名,只能用公钥验签。

常见的非对称加密算法有:RSA、ECC(椭圆曲线密码学)、SM2(国密)等。在Bootloader安全启动场景中,RSA和ECDSA是最常用的两种数字签名算法。

算法 密钥长度 签名速度 验签速度 安全性(同等强度)
RSA 2048/4096位
ECDSA 256/384位 较快 更高(同等密钥长度下)

你可能会问:“为什么Bootloader里不用对称加密来做签名验证?” 原因很简单:对称加密无法解决“信任链”的问题。 你想,如果Bootloader里预置了一个对称密钥,那这个密钥本身谁来保护?一旦泄露,整个安全体系就崩塌了。

而非对称加密就不一样了。Bootloader里只需要预置公钥,私钥放在安全的签名服务器上。公钥即使被公开,攻击者也拿它没办法——他无法用公钥伪造一个合法的签名。

我的经验:在资源极其受限的MCU(比如Cortex-M0)上,RSA-2048的验签时间大约在几百毫秒到1秒左右。如果对启动时间有严格要求,可以考虑使用ECDSA,它的验签速度更快,而且密钥长度更短。

三、哈希函数:数据的“指纹”

哈希函数,也叫散列函数。它的作用是把任意长度的输入数据,映射成一个固定长度的输出,这个输出叫做哈希值摘要

哈希函数有几个重要特性:

  • 单向性:从哈希值无法反推出原始数据。说白了,就是“有去无回”。
  • 抗碰撞性:很难找到两个不同的输入,产生相同的哈希值。
  • 雪崩效应:输入数据哪怕只改变一个比特,哈希值也会发生巨大变化。

在嵌入式安全领域,SHA-256是使用最广泛的哈希算法。它输出256位(32字节)的哈希值,安全性足够应对目前绝大多数应用场景。

我记得有一次,我在调试一个OTA升级的签名验证流程。固件明明没变,但签名验证总是失败。查了半天,发现是计算哈希值时,把固件末尾的填充字节也算进去了。嗯,哈希计算的范围必须和签名时完全一致,差一个字节都不行。 这个坑,我替你们踩过了。

注意:SHA-256虽然安全,但不要把它和“加密”混为一谈。哈希是单向的,不可逆的。加密是可逆的。很多初学者会把这两个概念搞混,面试时一问一个准。

四、数字签名原理:RSA与ECDSA

数字签名,是哈希函数和非对称加密的“组合拳”。它的核心流程是这样的:

  1. 签名方(比如服务器):
    • 对固件计算SHA-256哈希值,得到摘要。
    • 私钥对摘要进行加密(或签名算法中的特定运算),得到签名。
    • 将固件和签名一起发布。
  2. 验证方(比如Bootloader):
    • 对收到的固件计算SHA-256哈希值,得到摘要A。
    • 公钥对签名进行解密(或验签运算),得到摘要B。
    • 比较摘要A和摘要B。如果一致,说明固件是合法的、未被篡改的。

你看,这个流程巧妙地解决了两个问题:完整性验证(固件有没有被改过?)和身份认证(这个固件是不是来自合法的发布方?)。

具体到算法实现上:

  • RSA签名:常用的有RSA-PSS和RSA-PKCS1v1.5。我个人更推荐RSA-PSS,它在安全性上有一些改进,虽然计算量稍大一点。
  • ECDSA签名:基于椭圆曲线密码学。它的签名长度更短(64字节 vs RSA的256字节),非常适合带宽受限的嵌入式场景。
避坑指南:我曾经在移植OpenSSL的ECDSA验签代码到MCU时,发现验签总是失败。排查了两天,最后发现是字节序的问题——PC端是大端序,而MCU是小端序。签名数据在传输过程中,字节序没有做统一处理。所以,跨平台的数据交换,一定要明确字节序、对齐方式等细节。

五、在Bootloader中的实际应用

好了,理论讲完了。咱们来看看这些密码学知识在Bootloader里是怎么落地的。

一个典型的安全启动流程是这样的:

  1. 芯片上电,Bootloader开始执行。
  2. Bootloader从Flash中读取固件镜像和签名数据。
  3. Bootloader对固件计算SHA-256哈希值。
  4. Bootloader使用预置的公钥,对签名进行验签。
  5. 如果验签通过,跳转到固件入口执行;否则,进入错误处理(比如停止启动、进入恢复模式)。

这里有一个关键点:公钥必须安全地存储在Bootloader中。 通常的做法是,在芯片出厂时,将公钥烧录到一次性可编程(OTP)存储器中,或者存储在受保护的Flash区域。这样,即使攻击者读取了Flash内容,也无法修改公钥。

另外,我建议在Bootloader中实现多级签名验证。比如,第一级验证Bootloader自身的签名(由芯片厂商签名),第二级验证应用固件的签名(由设备厂商签名)。这样,即使应用固件的私钥泄露,攻击者也无法伪造Bootloader。

一个小技巧:在验签之前,可以先对固件进行CRC校验。CRC计算速度快,可以快速过滤掉明显损坏的固件。只有CRC通过后,才进行耗时的SHA-256和RSA/ECDSA验签。这样能有效提升启动速度。

好了,今天的课就到这里。密码学基础是Bootloader安全启动的基石,理解这些概念,你才能看懂后续章节中那些复杂的签名验证代码。下一讲,我们会深入探讨安全启动链的构建,包括信任根(RoT)、安全存储、以及如何防止回滚攻击。到时候见!