2. 固件与签名基础

各位做固件安全的同行,咱们今天聊点实在的。密码学这东西,听起来高大上,其实说白了就是几把锁和几把钥匙的事。我在嵌入式安全这行摸爬滚打了十几年,见过太多因为密码学基础不牢,导致整个安全体系崩塌的案例。

嗯,咱们这一章不讲虚的,直接上干货。对称加密、非对称加密、哈希函数、数字签名,这四个概念是固件签名的地基。地基不稳,房子再漂亮也得塌。

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

对称加密,顾名思义,加密和解密用的是同一把密钥。就像你家的门锁,用同一把钥匙锁门和开门。

我刚开始做嵌入式时,觉得对称加密太简单了,不就是 AES 吗?后来踩了坑才知道,简单的东西往往最容易出问题。

核心要点:对称加密速度快,适合大量数据加密。但密钥分发是个大麻烦——你怎么把密钥安全地交给对方?

常见的对称加密算法有:

  • AES(Advanced Encryption Standard)—— 目前最主流,密钥长度 128/192/256 位
  • DES(Data Encryption Standard)—— 太老了,56 位密钥,现在用暴力破解分分钟搞定
  • 3DES(Triple DES)—— DES 的加强版,但效率低,不推荐新项目用
  • SM4 —— 国标算法,国内项目必须考虑

我在一个 IoT 项目里遇到过这样的问题:设备固件升级包用 AES 加密,但密钥硬编码在代码里。你想想看,这跟没锁门有什么区别?反编译工具一跑,密钥就出来了。

避坑指南:我曾经见过一个团队,把 AES 密钥直接写在头文件里,还上传到了公开的 GitHub 仓库。嗯,后果可想而知。密钥必须安全存储,最好用硬件安全模块(HSM)或安全元件(SE)来保护。

非对称加密:公钥私钥,各司其职

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

说白了,公钥就像一把锁,谁都可以拿来锁东西;私钥就是唯一的钥匙,只有你能打开。

特性 对称加密 非对称加密
密钥数量 1 个 2 个(公钥 + 私钥)
加密速度 快(适合大数据) 慢(适合小数据)
密钥分发 困难 公钥可公开
典型算法 AES, SM4 RSA, ECC, SM2
典型用途 数据加密 密钥交换、数字签名

常见的非对称算法:

  • RSA —— 经典算法,基于大整数分解难题。密钥长度至少 2048 位,推荐 4096 位
  • ECC(椭圆曲线密码学)—— 同等安全强度下,密钥比 RSA 短得多。256 位 ECC 约等于 3072 位 RSA
  • SM2 —— 国标椭圆曲线算法,国内项目首选

个人经验:在资源受限的嵌入式设备上,我建议优先考虑 ECC。为什么?因为 RAM 和 Flash 都有限,ECC 的密钥和签名都更小,计算也更快。我在一个 STM32 项目上做过对比,同样安全等级,ECC 签名比 RSA 快了将近 10 倍。

哈希函数:数据的指纹

哈希函数,说白了就是给数据算一个「指纹」。不管输入多大,输出都是固定长度。而且,哪怕只改一个比特,指纹也会完全变样。

哈希函数有几个关键特性:

  1. 单向性:从哈希值无法反推出原始数据
  2. 抗碰撞性:很难找到两个不同数据有相同的哈希值
  3. 雪崩效应:输入微小变化,输出天翻地覆

常用的哈希算法:

  • SHA-256 —— 输出 256 位,目前最常用
  • SHA-3 —— 新一代标准,安全性更高
  • SM3 —— 国标哈希算法,输出 256 位
  • MD5 —— 128 位,已经不安全了,别用

注意:MD5 和 SHA-1 已经被证明存在碰撞攻击。我见过有厂商还在用 MD5 做固件完整性校验,这跟纸糊的锁没什么区别。至少要用 SHA-256。

数字签名:防伪造、防篡改、防抵赖

数字签名是非对称加密和哈希函数的组合应用。它解决了三个问题:

  • 身份认证:确认签名者是谁
  • 完整性:数据没有被篡改
  • 不可抵赖:签名者不能否认签过名

签名过程其实很简单:

  1. 对原始数据计算哈希值
  2. 用私钥对哈希值加密,得到签名
  3. 把原始数据和签名一起发给对方

验证过程:

  1. 用公钥解密签名,得到哈希值 A
  2. 对收到的原始数据计算哈希值 B
  3. 比较 A 和 B,一致则验证通过
// 伪代码示例:固件签名与验证
// 签名端(私钥签名)
hash = SHA256(firmware_data)
signature = RSA_Sign(private_key, hash)
// 输出:firmware_data + signature

// 验证端(公钥验证)
hash_received = SHA256(firmware_data)
hash_decrypted = RSA_Verify(public_key, signature)
if (hash_received == hash_decrypted) {
    printf("固件验证通过,可以升级\n");
} else {
    printf("固件被篡改,拒绝升级\n");
}

为什么先哈希再签名?因为非对称加密慢。对大固件直接签名,性能扛不住。先哈希压缩成固定长度,再签名,效率高得多。这也是实际工程中的标准做法。

知识体系总览

下面这张图把本章的核心逻辑串起来了。我建议你多看几遍,理解各个概念之间的关系。

密码学基础(上)知识体系 密码学基础 对称加密 非对称加密 哈希函数 AES SM4 RSA ECC SM2 SHA-256 SM3 数字签名 = 哈希函数 + 非对称加密 身份认证 完整性校验 不可抵赖 固件签名联调的核心:用私钥签名,用公钥验证,确保固件来源可信、内容完整

实际工程中的选择建议

做固件签名联调时,怎么选算法?我个人的经验是:

  • 签名算法:优先 ECC(如 ECDSA)或 SM2。RSA 也能用,但密钥太长,嵌入式设备吃不消
  • 哈希算法:SHA-256 或 SM3。别用 MD5 和 SHA-1,真的不安全
  • 密钥长度:ECC 256 位起步,RSA 2048 位起步
  • 国密要求:国内项目必须用 SM2 + SM3 + SM4 全套国密算法

一个小技巧:在联调阶段,可以先在 PC 上用 OpenSSL 生成测试密钥和签名,验证流程通了再移植到嵌入式平台。这样能省不少调试时间。我每次做新项目都这么干。