3. 密钥管理基础:公钥与私钥的概念、密钥生成流程、密钥存储安全规范

说实话,很多做固件的兄弟一听到「密钥管理」就头大。我当年也一样,觉得这是安全团队的事。直到有一次,我负责的产品在产线联调时签名死活通不过,折腾了两天,最后发现是密钥格式搞错了。嗯,从那以后,我再也不敢轻视这块了。

这一节,咱们就把密钥管理的基础打扎实。你想想看,固件签名说白了就是用一把「私钥」给固件打个标记,然后用一把「公钥」去验证这个标记是不是真的。这两把钥匙怎么来的、怎么存、怎么用,直接决定了你的签名体系靠不靠谱。

3.1 公钥与私钥:一对天生的搭档

非对称加密里,公钥和私钥是成对出现的。我习惯这么理解:私钥是「签名用的」,公钥是「验签用的」。私钥必须保密,谁拿到谁就能冒充你签名;公钥可以公开,谁拿到都能验证签名是不是你签的。

特性 私钥 (Private Key) 公钥 (Public Key)
用途 对固件进行签名 验证固件签名是否有效
保密性 绝对保密,仅签名者持有 可以公开,嵌入设备或发布
泄露后果 攻击者可伪造合法固件 无安全风险,但可能被替换
存储位置 HSM、安全芯片、加密服务器 固件头、设备存储区

核心原则:私钥永远不应该离开它被生成的安全环境。公钥可以随便分发,但必须保证其完整性——也就是说,你要确保设备拿到的公钥确实是你的,而不是被攻击者替换过的。

3.2 密钥生成流程:从零到一

生成一对密钥,听起来高大上,其实步骤很清晰。我个人习惯用 OpenSSL 命令行工具来做,因为它跨平台、生态好。下面我带你走一遍标准流程。

3.2.1 选择算法和密钥长度

目前固件签名领域,主流选择是 RSA-2048/4096 或 ECDSA P-256/P-384。RSA 兼容性好,但密钥长、签名慢;ECDSA 密钥短、性能好,但实现复杂一点。

我建议:
- 新项目优先选 ECDSA P-256,性能和安全性平衡得很好。
- 如果兼容旧设备或芯片不支持 ECC,那就用 RSA-2048。

3.2.2 生成私钥

以 ECDSA P-256 为例,命令很简单:

# 生成 ECDSA P-256 私钥
openssl ecparam -genkey -name prime256v1 -out private_key.pem

# 查看私钥信息
openssl ec -in private_key.pem -text -noout

生成的文件 private_key.pem 就是你的私钥。注意,这个文件一旦丢失或泄露,后果很严重。我在项目中遇到过有人把私钥文件直接提交到 Git 仓库的……嗯,那场面,不提了。

3.2.3 导出公钥

从私钥里提取公钥:

# 从私钥导出公钥
openssl ec -in private_key.pem -pubout -out public_key.pem

# 查看公钥内容
openssl ec -pubin -in public_key.pem -text -noout

公钥文件 public_key.pem 可以嵌入到 Bootloader 或固件中,用于验签。

3.2.4 生成签名

有了私钥,就可以对固件进行签名了:

# 对固件文件进行签名
openssl dgst -sha256 -sign private_key.pem -out firmware.sig firmware.bin

这个 firmware.sig 就是签名数据,通常会和固件打包在一起,或者单独烧录到指定分区。

我的习惯:生成密钥时,我会同时生成一个「备份私钥」并加密存储,防止原始私钥损坏。但备份必须和原始私钥分开存放,不能放在同一个服务器上。

3.3 密钥存储安全规范:别让钥匙丢了

密钥生成只是第一步,怎么存才是真正的考验。我曾经见过一个团队,把私钥明文放在 CI 服务器的环境变量里……结果 CI 被入侵,整个产品线的固件都被伪造了。教训惨痛。

3.3.1 私钥存储的黄金法则

  • 永远不要明文存储私钥。 至少要用 AES-256 加密后再存。
  • 使用硬件安全模块 (HSM)。 私钥在 HSM 内部生成,永远不导出。签名操作也在 HSM 内部完成。
  • 访问控制。 只有授权人员才能接触私钥。建议使用「多人审批」机制,比如需要两个人同时输入密码才能使用私钥。
  • 审计日志。 每次私钥的使用都要记录:谁、什么时间、签了什么固件。

3.3.2 公钥存储的注意事项

公钥虽然可以公开,但必须保证其完整性。常见的做法是:

  • 将公钥哈希值(指纹)烧录到芯片的一次性可编程 (OTP) 区域。
  • 在 Bootloader 中硬编码公钥,并加上写保护。
  • 使用证书链,由根证书签发中间证书,设备只信任根证书。

警告:千万不要把公钥放在可被用户随意修改的存储区(如外部 Flash 的普通分区)。攻击者可以替换公钥,然后用他自己的私钥签名恶意固件,你的整个安全体系就形同虚设了。

3.4 知识体系总览

下面这张图,把密钥管理的核心逻辑串起来了。你可以把它当作一个快速参考。

固件签名密钥管理知识体系 固件签名密钥管理知识体系 密钥生成 密钥存储 密钥使用 选择算法 生成私钥 导出公钥 HSM/安全芯片 加密存储 访问控制 固件签名 验签 证书链 核心原则 私钥永不离开安全环境 | 公钥必须保证完整性 | 密钥使用必须可审计 推荐算法:ECDSA P-256 或 RSA-2048

3.5 避坑指南:我踩过的那些坑

最后,分享几个我亲身经历过的教训,希望能帮你少走弯路。

  • 我曾经把私钥和源码放在同一个 Git 仓库里。 结果代码托管平台被拖库,私钥泄露。从那以后,我坚持私钥必须独立管理,使用专门的密钥管理系统。
  • 我曾经用错了密钥格式。 芯片 Bootloader 要求 DER 格式,我给了 PEM,联调时签名验证一直失败。排查了一整天才发现是格式问题。现在我会在项目初期就确认好芯片支持的密钥格式。
  • 我曾经没有备份私钥。 有一次 HSM 故障,私钥无法导出,整个产品线的签名流程停摆。后来我养成了「生成即备份」的习惯,备份加密后存放在异地。

一个小建议:在开发阶段,可以使用测试密钥对。但测试密钥和正式密钥必须严格区分,不能混用。我习惯在密钥文件名里加上 _DEV 或 _PROD 后缀,一目了然。