数字签名基础:非对称加密原理、哈希函数的作用、数字签名的生成与验证流程
各位同学,今天我们来聊聊数字签名。说实话,这是整个安全更新通道的基石。没有它,你下载的固件更新包到底是不是官方发布的,根本没法判断。
我在早期做嵌入式设备OTA升级时,就吃过这个亏。当时团队图省事,只用了简单的CRC校验,结果被中间人攻击篡改了固件,设备批量变砖。嗯,从那以后,我再也不敢轻视数字签名了。
非对称加密原理:一把钥匙开一把锁,但钥匙分两把
先说说非对称加密。你想想看,对称加密就像你家大门钥匙——同一把钥匙既能锁门也能开门。但问题来了:这把钥匙怎么安全地交给对方?
非对称加密就不一样了。它生成一对密钥:公钥和私钥。公钥可以公开给任何人,私钥必须自己藏好。
核心原则:
- 公钥加密的数据,只有对应的私钥能解密
- 私钥加密的数据,只有对应的公钥能解密
我个人习惯把公钥想象成一个「投信口」,谁都能往里塞信。但打开信箱的钥匙(私钥)只有你一个人有。反过来,你用私钥签名的东西,别人用你的公钥一验就知道是你干的——这就是数字签名的本质。
常见的非对称算法有RSA、ECDSA、Ed25519。我在项目中用得最多的是ECDSA,尤其是基于NIST P-256曲线的。为什么?因为它的密钥比RSA短得多,但安全强度相当,对嵌入式设备的存储和计算压力更小。
| 算法 | 密钥长度(位) | 签名长度(字节) | 典型应用场景 |
|---|---|---|---|
| RSA | 2048 / 4096 | 256 / 512 | 传统PKI、代码签名 |
| ECDSA (P-256) | 256 | 64 | IoT固件更新、TLS |
| Ed25519 | 256 | 64 | 现代安全更新、SSH |
我的建议:新项目优先选Ed25519或ECDSA P-256。RSA虽然成熟,但密钥太长,签名也大,在带宽有限的更新通道里不太划算。
哈希函数的作用:给数据打一个「指纹」
非对称加密虽然强大,但有个问题——慢。你想想看,一个固件包动辄几十MB,直接用私钥加密整个文件,计算量太大了,设备端根本扛不住。
这时候哈希函数就派上用场了。哈希函数能把任意长度的数据,压缩成一个固定长度的摘要(比如SHA-256输出32字节)。而且它有这几个特性:
- 单向性:从摘要反推原始数据,几乎不可能
- 抗碰撞性:很难找到两个不同的数据,产生相同的摘要
- 雪崩效应:输入改一个比特,输出完全变样
说白了,哈希值就是数据的「数字指纹」。你改了一丁点内容,指纹就变了。我在项目中遇到过有人问:「能不能用MD5?」我的回答永远是——不行。MD5已经被证明可以人为制造碰撞,SHA-1也基本废了。现在最低标准是SHA-256。
避坑指南:我曾经在一个遗留项目里看到还在用SHA-1做固件签名校验。当时我坚持要求升级到SHA-256,项目经理觉得没必要。结果半年后,安全审计直接亮了红灯,被迫紧急回炉。嗯,有些坑真的没必要亲自踩。
数字签名的生成与验证流程
好了,把非对称加密和哈希函数结合起来,就是数字签名。流程其实不复杂,我画了一张图帮你理解:
流程其实就三步:
- 发送方:对原始数据做哈希,得到摘要。然后用私钥加密这个摘要,生成数字签名。最后把「原始数据 + 数字签名」一起发出去。
- 接收方:收到数据后,用同样的哈希函数对原始数据计算,得到摘要B。同时用发送方的公钥解密数字签名,得到摘要A。
- 比较:如果摘要A == 摘要B,说明数据没被改过,而且确实是你信任的那一方签的。
关键理解:数字签名不是加密数据本身,而是加密数据的哈希值。这样做既保证了效率(只加密32字节),又保证了完整性(哈希值能代表整个文件)。
实际项目中的签名策略
在安全更新通道里,数字签名通常有两种用法:
- 内嵌签名:签名直接附加在固件包尾部。设备收到后先验签名,再刷写。这种方式简单,但签名和固件一起传输,如果传输通道不安全,攻击者可以替换整个包。
- 分离签名:签名单独放在一个元数据文件里,或者通过另一个安全通道下发。我比较推荐这种方式,尤其是配合硬件安全模块(HSM)使用时,私钥永远不会暴露在应用层。
我的经验:在IoT设备上,我通常采用「双签名」策略——固件包用ECDSA签名,同时元数据文件再用RSA签一次。虽然多了一步,但能兼容不同安全等级的设备。老设备只验RSA,新设备两个都验。