4、刷写文件格式:S19/HEX/BIN格式解析、加密与签名、文件完整性校验
好,咱们进入第四章。这一章聊的是刷写文件的“皮囊”和“灵魂”。
你想想看,ECU刷写,本质上就是把一堆二进制数据塞进芯片里。但怎么塞?用什么格式塞?塞进去之后怎么保证没被人动过手脚?这就是我们今天要解决的问题。
我个人习惯把刷写文件分成三层来看:表示层(S19/HEX/BIN)、安全层(加密与签名)、校验层(完整性校验)。咱们一层一层剥开。
4.1 三种主流格式:S19、HEX、BIN
先说BIN。BIN是最纯粹的格式,没有地址信息,没有校验和,就是赤裸裸的二进制数据流。我在项目中遇到过,有些刚入行的同事直接把BIN文件烧进去,结果程序跑飞了——因为不知道起始地址。BIN文件必须配合烧录工具或配置文件指定地址,否则就是盲人摸象。
再说HEX(Intel HEX)。这个格式带地址了。每一行以冒号开头,结构是::长度 地址 类型 数据 校验和。类型有00(数据)、01(文件结束)、04(扩展线性地址)等。我个人觉得HEX比S19更紧凑,但可读性稍差。
最后是S19(Motorola S-record)。这是汽车行业的老大哥。每一行以'S'开头,后面跟类型(S0/S1/S2/S3/S5/S7/S8/S9)。S3是32位地址,S2是24位,S1是16位。嗯,这里要注意:S19的地址是高位在前,低位在后,和HEX正好相反。我曾经因为搞混这个,刷废了一块板子,从那以后我每次都会先看一眼文件头。
核心区别总结:
- BIN:纯数据,无地址,体积最小,适合流式传输
- HEX:带地址和校验,每行独立,适合分段烧录
- S19:带地址和校验,支持多种地址宽度,汽车行业标准
举个例子,一个简单的S19数据行:
S214 0000 48656C6C6F20576F726C64 5A
解释一下:S2表示24位地址,14是数据长度(20字节),0000是地址,后面是ASCII码"Hello World",5A是校验和。
4.2 加密与签名:给文件上把锁
刷写文件在传输过程中,最怕什么?被篡改。你想想看,如果有人在中间把固件换成了恶意代码,那整辆车都可能变成炸弹。所以,加密和签名是必须的。
加密是为了保密。常用的有AES-128/256。我个人习惯用AES-256-CBC模式,因为它的初始化向量(IV)能增加破解难度。但要注意,ECU的算力有限,加密算法不能太复杂,否则刷写时间会很长。我在一个项目中就遇到过,加密后刷写时间从5分钟变成了20分钟,最后不得不改用硬件加速。
签名是为了防篡改和防伪造。常用的是RSA或ECDSA。签名过程是这样的:
- 对固件做哈希(比如SHA-256),得到摘要
- 用私钥对摘要加密,得到签名
- 将签名附加到固件后面
ECU收到后,用公钥解密签名,得到摘要A;再对收到的固件做哈希,得到摘要B。如果A==B,说明固件没被改过。
避坑指南:我曾经遇到过签名验证通过,但固件还是跑不起来的情况。后来发现是哈希算法不匹配——ECU用的是SHA-256,但工具链用的是SHA-1。所以,一定要确认算法一致性。
另外,密钥管理是个大坑。私钥泄露了,整个产品线都得报废。我建议把私钥放在HSM(硬件安全模块)里,或者至少用密码保护。公钥可以放在ECU的OTP(一次性可编程)区域,防止被篡改。
4.3 文件完整性校验:确保数据没丢没坏
加密和签名防的是人为篡改,但传输过程中还可能发生比特翻转、丢包等问题。这时候就需要完整性校验了。
常用的校验方式有:
- CRC32:速度快,但碰撞概率高,适合小文件
- SHA-256:安全,但计算量大,适合大文件
- MD5:不推荐,已被证明不安全
我个人习惯的做法是:分块校验 + 整体校验。比如每1KB数据算一个CRC32,最后再对整个文件算一个SHA-256。这样既能快速定位错误块,又能保证整体安全。
举个例子,一个典型的刷写流程:
1. 读取S19文件,解析出地址和数据
2. 对每块数据计算CRC32,存入临时数组
3. 发送数据块 + CRC32
4. ECU收到后,计算本地CRC32,对比
5. 如果一致,回复ACK;否则回复NACK,请求重传
6. 所有块传输完成后,发送整体SHA-256
7. ECU计算整体哈希,对比
8. 如果一致,开始刷写;否则报错
注意:有些ECU的RAM很小,无法缓存整个固件。这时候只能做流式校验——边收边校验,但这样就不能做整体哈希了。我的解决方案是:先做分块CRC,最后再做一次整体签名验证。签名验证本身包含了哈希,所以可以替代整体校验。
嗯,这里还要提一下“刷写中断恢复”。如果刷到一半断电了,怎么办?我建议在刷写前先备份当前固件,或者记录刷写进度。下次上电时,从断点继续。完整性校验在这里的作用是:确认已刷写的部分是正确的,未刷写的部分需要重传。
4.4 实战建议:如何选择格式和校验策略
说了这么多,到底怎么选?我给出一个参考:
| 场景 | 推荐格式 | 校验策略 |
|---|---|---|
| OTA远程刷写 | S19 + 加密 + 签名 | 分块CRC + 整体SHA-256 |
| 产线烧录 | BIN + 地址映射表 | 整体CRC32 |
| 诊断仪刷写 | HEX | 逐行校验和 |
| Bootloader更新 | S19 + 签名 | 分块CRC + 签名验证 |
我个人最常用的是S19 + AES-256-CBC + ECDSA + 分块CRC。这个组合在安全性和性能之间取得了平衡。当然,具体还要看ECU的硬件能力。有些老芯片连AES加速都没有,那就只能用软件实现了,速度会慢一些。
最后,记住一句话:没有绝对的安全,只有相对的合适。加密和校验的目的是增加攻击成本,而不是完全杜绝攻击。只要让攻击者觉得“划不来”,你的系统就是安全的。
好,这一章就到这里。下一章我们聊聊刷写流程中的“握手协议”——怎么让ECU乖乖听话,开始刷写。