4. 固件签名工具链搭建:OpenSSL 安装与密钥生成
好,咱们进入实战环节。前面几章讲了签名验证的理论,现在该动手了。这一章的核心就三件事:装好 OpenSSL、生成密钥对、用它对固件做哈希和签名。
我个人习惯把工具链搭建放在课程前半段,因为后面所有章节的代码、脚本、流程都依赖这套环境。你想想看,如果连签名工具都没配好,后面讲再多也是纸上谈兵。
4.1 OpenSSL 安装与配置
OpenSSL 是嵌入式签名领域的事实标准。我见过不少项目用自研的签名工具,最后都因为兼容性问题回退到 OpenSSL。所以,别折腾,直接用。
4.1.1 Linux 环境安装
大多数 Linux 发行版都预装了 OpenSSL。你可以先检查一下版本:
openssl version
如果没装,或者版本太旧(低于 1.1.1),建议更新。我个人习惯用包管理器安装:
# Ubuntu / Debian
sudo apt-get update
sudo apt-get install openssl libssl-dev
# CentOS / RHEL
sudo yum install openssl openssl-devel
openssl version -a 查看编译参数。确保支持你需要的算法,比如 EC(椭圆曲线)。我曾经遇到过客户提供的 OpenSSL 没编译 EC 支持,折腾了半天才发现。
4.1.2 Windows 环境安装
Windows 下我推荐两种方式:
- 方式一: 下载官方安装包(slproweb.com/products/Win32OpenSSL.html),选 Light 版本就行。
- 方式二: 用 WSL(Windows Subsystem for Linux),直接在 Linux 子系统里操作。我个人更倾向这种方式,因为脚本环境统一,避免路径和换行符的坑。
安装完后,记得把 OpenSSL 的 bin 目录加到系统 PATH 里。验证方法很简单:打开命令行,输入 openssl version,能看到版本号就说明成了。
4.2 生成 RSA / ECC 密钥对
密钥对是签名的根基。公钥要烧到设备里,私钥必须保存在安全的构建服务器上。这个原则一定要记住。
4.2.1 生成 RSA 密钥对
RSA 是目前最广泛使用的非对称算法。我一般用 2048 位,安全性和性能比较均衡。4096 位更安全,但签名和验签都慢,嵌入式设备上尤其明显。
# 生成 RSA 私钥(2048 位)
openssl genpkey -algorithm RSA -pkeyopt rsa_keygen_bits:2048 -out private_rsa.pem
# 从私钥提取公钥
openssl rsa -pubout -in private_rsa.pem -out public_rsa.pem
4.2.2 生成 ECC 密钥对
ECC(椭圆曲线密码学)的优势是密钥短、速度快。对于资源受限的 IoT 设备,ECC 比 RSA 更友好。我推荐使用 prime256v1(也叫 secp256r1),这是 NIST 标准曲线,兼容性最好。
# 生成 ECC 私钥(prime256v1 曲线)
openssl ecparam -genkey -name prime256v1 -out private_ecc.pem
# 从私钥提取公钥
openssl ec -pubout -in private_ecc.pem -out public_ecc.pem
为什么选 prime256v1?说白了,大多数安全芯片和 MCU 的硬件加速器都支持这条曲线。你选一条冷门曲线,可能连硬件加速都用不了,纯软件算签名会慢得让人崩溃。
4.2.3 RSA 与 ECC 对比
| 对比项 | RSA-2048 | ECC-256 (prime256v1) |
|---|---|---|
| 密钥长度 | 2048 位 | 256 位 |
| 签名长度 | 256 字节 | 64 字节 |
| 签名速度 | 较慢 | 较快 |
| 验签速度 | 较快 | 较快 |
| 硬件加速支持 | 广泛 | 广泛(主流 MCU) |
| 推荐场景 | 网关、服务器端 | IoT 终端、MCU |
我个人在车规级 MCU 项目里更倾向 ECC。签名短,传输快,验签时占用的 RAM 也少。但如果你做的是 Linux 网关或者服务器端的固件验证,RSA 也完全够用。
4.3 使用 OpenSSL 对固件进行哈希与签名
密钥有了,接下来就是给固件“盖戳”。流程很简单:先算哈希,再用私钥加密哈希值,得到签名。
4.3.1 计算固件哈希
哈希算法我推荐 SHA-256。SHA-1 已经不安全了,SHA-512 又太慢。SHA-256 是当前最平衡的选择。
# 计算固件文件的 SHA-256 哈希值
openssl dgst -sha256 -binary firmware.bin > firmware.hash
这条命令会输出二进制格式的哈希值。你也可以用 -hex 参数输出十六进制文本,方便调试时肉眼查看。
4.3.2 生成签名
用私钥对哈希值签名。RSA 和 ECC 的命令略有不同:
# RSA 签名
openssl dgst -sha256 -sign private_rsa.pem -out firmware.sig firmware.bin
# ECC 签名
openssl dgst -sha256 -sign private_ecc.pem -out firmware.sig firmware.bin
嗯,这里要注意:-sign 参数会自动完成哈希计算和签名两步。你不需要先手动算哈希再签名,OpenSSL 帮你做了。但为了教学清晰,我前面还是拆开演示了。
4.3.3 验证签名
签名生成后,一定要验证一遍。我习惯在构建脚本里自动执行验证,确保签名没出错。
# RSA 验签
openssl dgst -sha256 -verify public_rsa.pem -signature firmware.sig firmware.bin
# ECC 验签
openssl dgst -sha256 -verify public_ecc.pem -signature firmware.sig firmware.bin
如果输出 Verified OK,说明签名正确。如果输出 Verification Failure,赶紧检查密钥是否匹配、固件是否被修改过。
4.4 完整签名流程
把上面几步串起来,就是一个完整的固件签名流水线。我画了一张流程图,帮你理清整体逻辑。
流程其实不复杂。固件进来,算哈希,用私钥签名,最后把固件和签名打包在一起。设备端收到后,用公钥验签,比对哈希,就能确认固件是否完整、是否来自可信源。
4.5 本章小结
这一章我们搭好了签名工具链。你学会了:
- 安装和配置 OpenSSL
- 生成 RSA 和 ECC 密钥对
- 用 OpenSSL 对固件做哈希和签名
- 验证签名是否正确