457 lines
12 KiB
Markdown
457 lines
12 KiB
Markdown
# 车载系统安全升级流程说明
|
||||
|
|
|
|||
|
|
## 一、核心原理(一句话说明)
|
|||
|
|
|
|||
|
|
采用 **RSA2048 + SHA256** 数字签名技术,确保升级包来源可信、内容完整,防止恶意软件植入。
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
## 二、算法原理
|
|||
|
|
|
|||
|
|
### 2.1 技术组合
|
|||
|
|
|
|||
|
|
```
|
|||
|
|
RSA2048 + SHA256 统称为 SHA256withRSA
|
|||
|
|
- SHA-256:计算文件哈希值(32字节指纹)
|
|||
|
|
- RSA2048:公钥验证签名(2048位密钥强度)
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
### 2.2 三个核心步骤
|
|||
|
|
|
|||
|
|
```
|
|||
|
|
第一步:计算文件的哈希值
|
|||
|
|
固件文件 → SHA-256哈希算法 → 32字节哈希值
|
|||
|
|
|
|||
|
|
第二步:加载用于验证的公钥
|
|||
|
|
PEM格式公钥 → Base64解码 → RSA公钥对象
|
|||
|
|
|
|||
|
|
第三步:验证签名
|
|||
|
|
哈希值 + 签名 + 公钥 → SHA256withRSA验证 → true/false
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
## 三、升级流程图
|
|||
|
|
|
|||
|
|
### 3.1 整体流程
|
|||
|
|
|
|||
|
|
```
|
|||
|
|
┌─────────────────────────────────────────────────────────┐
|
|||
|
|
│ 车载系统安全升级流程 │
|
|||
|
|
└─────────────────────────────────────────────────────────┘
|
|||
|
|
|
|||
|
|
用户操作:插入升级U盘
|
|||
|
|
↓
|
|||
|
|
系统检测:发现升级包(update_mcu.zip / update_soc.zip)
|
|||
|
|
↓
|
|||
|
|
┌─────────────────────────────────────┐
|
|||
|
|
│ 安全验证阶段(用户不可见) │
|
|||
|
|
├─────────────────────────────────────┤
|
|||
|
|
│ 1. 解压ZIP包 │
|
|||
|
|
│ ├─ 固件文件(cortex-gdm4.bin/update.zip)│
|
|||
|
|
│ └─ 签名文件(ValidationFile.ini) │
|
|||
|
|
│ │
|
|||
|
|
│ 2. 计算固件哈希值 │
|
|||
|
|
│ 固件文件 → SHA-256 → 32字节哈希 │
|
|||
|
|
│ │
|
|||
|
|
│ 3. 读取签名 │
|
|||
|
|
│ ValidationFile.ini → 提取sign=字段 │
|
|||
|
|
│ │
|
|||
|
|
│ 4. 验证签名 │
|
|||
|
|
│ 公钥解密签名 → 对比哈希值 │
|
|||
|
|
└─────────────────────────────────────┘
|
|||
|
|
↓
|
|||
|
|
├─ ✅ 验证通过
|
|||
|
|
│ ↓
|
|||
|
|
│ 继续升级流程
|
|||
|
|
│ ↓
|
|||
|
|
│ ┌─────────────────┐
|
|||
|
|
│ │ SOC升级: │
|
|||
|
|
│ │ UpdateEngine安装 │
|
|||
|
|
│ └─────────────────┘
|
|||
|
|
│ ┌─────────────────┐
|
|||
|
|
│ │ MCU升级: │
|
|||
|
|
│ │ 串口传输固件 │
|
|||
|
|
│ └─────────────────┘
|
|||
|
|
│ ↓
|
|||
|
|
│ 升级完成
|
|||
|
|
│ ↓
|
|||
|
|
│ 自动删除临时文件
|
|||
|
|
│ ↓
|
|||
|
|
│ 显示升级成功
|
|||
|
|
│
|
|||
|
|
└─ ❌ 验证失败
|
|||
|
|
↓
|
|||
|
|
中止升级
|
|||
|
|
↓
|
|||
|
|
自动删除临时文件
|
|||
|
|
↓
|
|||
|
|
显示验证失败提示
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
## 四、升级包格式
|
|||
|
|
|
|||
|
|
### 4.1 SOC升级包
|
|||
|
|
|
|||
|
|
```
|
|||
|
|
update.zip(注意:U盘中的文件名)
|
|||
|
|
├── update.zip (内层OTA升级包)
|
|||
|
|
└── ValidationFile.ini (签名文件)
|
|||
|
|
内容格式:sign=a1b2c3d4e5...(512个十六进制字符)
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
**⚠️ 重要说明**:
|
|||
|
|
- U盘中的文件名是 `update.zip`(不是 `update_soc.zip`)
|
|||
|
|
- 解压后的内层文件也叫 `update.zip`(双层同名结构)
|
|||
|
|
|
|||
|
|
### 4.2 MCU升级包
|
|||
|
|
|
|||
|
|
```
|
|||
|
|
update_mcu.zip
|
|||
|
|
├── cortex-gdm4.bin (MCU固件)
|
|||
|
|
└── ValidationFile.ini (签名文件)
|
|||
|
|
内容格式:sign=a1b2c3d4e5...(512个十六进制字符)
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
### 4.3 升级包命名对比
|
|||
|
|
|
|||
|
|
| 类型 | U盘文件名 | 解压后固件文件 | 签名文件 |
|
|||
|
|
|------|-----------|----------------|----------|
|
|||
|
|
| **MCU** | `update_mcu.zip` | `cortex-gdm4.bin` | `ValidationFile.ini` |
|
|||
|
|
| **SOC** | `update.zip` | `update.zip`(内层) | `ValidationFile.ini` |
|
|||
|
|
|
|||
|
|
### 4.4 ValidationFile.ini格式说明
|
|||
|
|
|
|||
|
|
```ini
|
|||
|
|
sign=<256字节的十六进制签名字符串>
|
|||
|
|
|
|||
|
|
示例:
|
|||
|
|
sign=a1b2c3d4e5f67890abcdef...(共512个字符)
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
## 五、核心代码实现
|
|||
|
|
|
|||
|
|
### 5.1 验证入口
|
|||
|
|
|
|||
|
|
```java
|
|||
|
|
// 验证入口位置
|
|||
|
|
McuM3Update.java:427 // MCU验证入口
|
|||
|
|
SocUpdate.java:180 // SOC验证入口
|
|||
|
|
|
|||
|
|
// 验证流程
|
|||
|
|
private boolean verify(File zipFile) {
|
|||
|
|
// 步骤1: 解压ZIP
|
|||
|
|
ZipUtils.unzipFile(zipFile, targetDir);
|
|||
|
|
|
|||
|
|
// 步骤2: 计算哈希
|
|||
|
|
byte[] fileHash = ZipFileVerifier.computeFileHash(updateFile);
|
|||
|
|
|
|||
|
|
// 步骤3: 读取签名
|
|||
|
|
byte[] signatureBytes = readSignBytes(signatureFile);
|
|||
|
|
|
|||
|
|
// 步骤4: 加载公钥
|
|||
|
|
PublicKey publicKey = ZipFileVerifier.loadPublicKey(pem);
|
|||
|
|
|
|||
|
|
// 步骤5: 验证签名
|
|||
|
|
boolean isValid = ZipFileVerifier.verifySignature(
|
|||
|
|
fileHash, signatureBytes, publicKey
|
|||
|
|
);
|
|||
|
|
|
|||
|
|
return isValid;
|
|||
|
|
}
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
### 5.2 核心验证算法
|
|||
|
|
|
|||
|
|
```java
|
|||
|
|
// 1. 计算SHA-256哈希
|
|||
|
|
public static byte[] computeFileHash(File file) {
|
|||
|
|
MessageDigest digest = MessageDigest.getInstance("SHA-256");
|
|||
|
|
FileInputStream fis = new FileInputStream(file);
|
|||
|
|
|
|||
|
|
byte[] buffer = new byte[1024];
|
|||
|
|
int bytesRead;
|
|||
|
|
while ((bytesRead = fis.read(buffer)) != -1) {
|
|||
|
|
digest.update(buffer, 0, bytesRead);
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
return digest.digest(); // 32字节哈希值
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// 2. 加载公钥
|
|||
|
|
public static PublicKey loadPublicKey(String publicKeyPEM) {
|
|||
|
|
// 去除PEM头尾标记
|
|||
|
|
String pemFormatted = publicKeyPEM
|
|||
|
|
.replace("-----BEGIN PUBLIC KEY-----", "")
|
|||
|
|
.replace("-----END PUBLIC KEY-----", "")
|
|||
|
|
.replaceAll("\\s", "");
|
|||
|
|
|
|||
|
|
// Base64解码
|
|||
|
|
byte[] decoded = Base64.getDecoder().decode(pemFormatted);
|
|||
|
|
|
|||
|
|
// 构造RSA公钥对象
|
|||
|
|
KeyFactory keyFactory = KeyFactory.getInstance("RSA");
|
|||
|
|
X509EncodedKeySpec keySpec = new X509EncodedKeySpec(decoded);
|
|||
|
|
return keyFactory.generatePublic(keySpec);
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// 3. 验证签名
|
|||
|
|
public static boolean verifySignature(
|
|||
|
|
byte[] fileHash,
|
|||
|
|
byte[] signatureBytes,
|
|||
|
|
PublicKey publicKey
|
|||
|
|
) {
|
|||
|
|
Signature signature = Signature.getInstance("SHA256withRSA");
|
|||
|
|
signature.initVerify(publicKey);
|
|||
|
|
signature.update(fileHash);
|
|||
|
|
return signature.verify(signatureBytes);
|
|||
|
|
}
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
## 六、安全保证
|
|||
|
|
|
|||
|
|
### 6.1 三重安全机制
|
|||
|
|
|
|||
|
|
```
|
|||
|
|
┌────────────────────────────────────────┐
|
|||
|
|
│ 第1层:文件完整性(防篡改) │
|
|||
|
|
│ SHA-256哈希校验,任何修改都会导致签名失效│
|
|||
|
|
├────────────────────────────────────────┤
|
|||
|
|
│ 第2层:数字签名(防伪造) │
|
|||
|
|
│ RSA2048私钥签名,无官方私钥无法伪造 │
|
|||
|
|
├────────────────────────────────────────┤
|
|||
|
|
│ 第3层:自动清理(防残留) │
|
|||
|
|
│ 升级完成/失败后自动删除临时文件 │
|
|||
|
|
└────────────────────────────────────────┘
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
### 6.2 安全性指标
|
|||
|
|
|
|||
|
|
| 安全项 | 技术参数 | 安全等级 |
|
|||
|
|
|--------|----------|----------|
|
|||
|
|
| 密钥强度 | RSA2048 | 军工级 |
|
|||
|
|
| 哈希算法 | SHA-256 | 抗碰撞 |
|
|||
|
|
| 签名长度 | 256字节 | 不可伪造 |
|
|||
|
|
| 验证准确性 | 100% | 确定性 |
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
## 七、异常处理流程
|
|||
|
|
|
|||
|
|
### 7.1 验证失败处理
|
|||
|
|
|
|||
|
|
```
|
|||
|
|
验证失败触发条件:
|
|||
|
|
├─ 签名不存在
|
|||
|
|
├─ 签名格式错误
|
|||
|
|
├─ 签名验证不通过
|
|||
|
|
└─ 文件被篡改
|
|||
|
|
|
|||
|
|
处理流程:
|
|||
|
|
验证失败 → 返回VERIFY_FAILURE
|
|||
|
|
→ UpdateService检测状态
|
|||
|
|
→ 自动删除临时文件
|
|||
|
|
→ 提示用户"验证失败,请联系供应商"
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
### 7.2 升级失败处理
|
|||
|
|
|
|||
|
|
```
|
|||
|
|
升级失败触发条件:
|
|||
|
|
├─ SOC升级:UpdateEngine返回错误码
|
|||
|
|
└─ MCU升级:MCU校验失败(0xE4返回非0x01)
|
|||
|
|
|
|||
|
|
处理流程:
|
|||
|
|
升级失败 → 返回INSTALL_FAILED
|
|||
|
|
→ UpdateService检测状态
|
|||
|
|
→ 自动删除临时文件
|
|||
|
|
→ 提示用户"升级失败"
|
|||
|
|
→ 系统恢复原状
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
## 八、关键代码位置
|
|||
|
|
|
|||
|
|
### 8.1 核心文件
|
|||
|
|
|
|||
|
|
```
|
|||
|
|
验证核心:
|
|||
|
|
ZipFileVerifier.java - RSA+SHA256验证算法
|
|||
|
|
ZipUtils.java - ZIP解压工具
|
|||
|
|
|
|||
|
|
升级处理:
|
|||
|
|
McuM3Update.java - MCU升级逻辑
|
|||
|
|
SocUpdate.java - SOC升级逻辑
|
|||
|
|
UpdateService.java - 升级服务总控
|
|||
|
|
|
|||
|
|
状态管理:
|
|||
|
|
UpdateState.java - 升级状态定义
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
### 8.2 关键方法
|
|||
|
|
|
|||
|
|
```
|
|||
|
|
验证流程:
|
|||
|
|
McuM3Update.verify() - MCU验证入口(:427)
|
|||
|
|
SocUpdate.verify() - SOC验证入口(:180)
|
|||
|
|
ZipFileVerifier.computeFileHash() - 计算哈希(:48)
|
|||
|
|
ZipFileVerifier.loadPublicKey() - 加载公钥(:30)
|
|||
|
|
ZipFileVerifier.verifySignature() - 验证签名(:19)
|
|||
|
|
|
|||
|
|
文件清理:
|
|||
|
|
UpdateService.deleteFile() - 删除临时文件(:392)
|
|||
|
|
UpdateService.deleteDirectory() - 递归删除(:408)
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
## 九、技术参数
|
|||
|
|
|
|||
|
|
### 9.1 算法参数
|
|||
|
|
|
|||
|
|
```
|
|||
|
|
加密算法:RSA2048
|
|||
|
|
- 密钥长度:2048位
|
|||
|
|
- 签名长度:256字节
|
|||
|
|
- 安全等级:军工级
|
|||
|
|
|
|||
|
|
哈希算法:SHA-256
|
|||
|
|
- 哈希长度:32字节
|
|||
|
|
- 抗碰撞性:2^128分之一
|
|||
|
|
- 单向性:不可逆
|
|||
|
|
|
|||
|
|
签名算法:SHA256withRSA
|
|||
|
|
- 标准:Java标准库
|
|||
|
|
- 性能:验证耗时 < 3秒
|
|||
|
|
- 准确性:100%确定性
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
### 9.2 文件参数
|
|||
|
|
|
|||
|
|
```
|
|||
|
|
升级包路径:
|
|||
|
|
SOC:/sdcard/zhongqi_soc_update/
|
|||
|
|
MCU:/sdcard/zhongqi_mcu_update/
|
|||
|
|
|
|||
|
|
内存占用:
|
|||
|
|
哈希计算缓冲区:1024字节
|
|||
|
|
解压临时空间:< 50MB
|
|||
|
|
总内存占用:< 5MB
|
|||
|
|
|
|||
|
|
时间性能:
|
|||
|
|
验证耗时:< 3秒
|
|||
|
|
解压耗时:根据文件大小
|
|||
|
|
升级总耗时:5-15分钟(取决于类型)
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
## 十、常见问题
|
|||
|
|
|
|||
|
|
### 10.1 技术问题
|
|||
|
|
|
|||
|
|
**Q1: 为什么选择RSA2048而不是AES?**
|
|||
|
|
```
|
|||
|
|
A: RSA是非对称加密,公钥公开、私钥保密,适合签名验证场景。
|
|||
|
|
AES是对称加密,密钥需要保密,不适合公开验证场景。
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
**Q2: SHA-256有什么优势?**
|
|||
|
|
```
|
|||
|
|
A: SHA-256是单向哈希函数,具有:
|
|||
|
|
- 抗碰撞性:无法找到两个相同哈希的文件
|
|||
|
|
- 单向性:无法从哈希值反推文件内容
|
|||
|
|
- 固定长度:任何文件都生成32字节哈希
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
**Q3: 为什么验证需要3秒?**
|
|||
|
|
```
|
|||
|
|
A: 包含三个步骤:
|
|||
|
|
1. 解压ZIP包(~1秒)
|
|||
|
|
2. 计算SHA-256哈希(~1秒,流式计算)
|
|||
|
|
3. RSA签名验证(~1秒)
|
|||
|
|
相比整个升级过程(5-15分钟),3秒可忽略不计。
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
### 10.2 实践问题
|
|||
|
|
|
|||
|
|
**Q4: 如何制作合法的升级包?**
|
|||
|
|
```
|
|||
|
|
A: 需要官方授权的签名工具:
|
|||
|
|
1. 准备固件文件(.bin / .zip)
|
|||
|
|
2. 使用官方签名工具生成签名
|
|||
|
|
3. 打包成ZIP(固件 + ValidationFile.ini)
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
**Q5: 升级失败会影响系统吗?**
|
|||
|
|
```
|
|||
|
|
A: 不会:
|
|||
|
|
- 验证失败:立即中止,删除临时文件
|
|||
|
|
- 升级失败:自动恢复原状
|
|||
|
|
- 断电保护:系统有回滚机制
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
**Q6: 可以复制别人的升级包吗?**
|
|||
|
|
```
|
|||
|
|
A: 可以,但需注意:
|
|||
|
|
- 设备型号必须匹配
|
|||
|
|
- 系统会自动检查版本标识
|
|||
|
|
- 不匹配会被拒绝(VERIFY_FAILURE)
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
## 十一、给同事的讲解要点
|
|||
|
|
|
|||
|
|
### 11.1 一句话总结
|
|||
|
|
|
|||
|
|
> "用私钥给文件哈希值签名,车端用公钥验证签名,通过哈希对比判断文件是否官方发布且未被篡改。"
|
|||
|
|
|
|||
|
|
### 11.2 核心流程三句话
|
|||
|
|
|
|||
|
|
```
|
|||
|
|
1. 解压ZIP → 计算固件哈希 → 读取签名
|
|||
|
|
2. 加载公钥 → 验证签名 → 对比哈希
|
|||
|
|
3. 验证通过 → 升级;验证失败 → 中止+清理
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
### 11.3 安全保证三句话
|
|||
|
|
|
|||
|
|
```
|
|||
|
|
1. 私钥只有官方有,无法伪造签名
|
|||
|
|
2. 哈希绑定文件内容,任何修改都会失效
|
|||
|
|
3. 验证失败立即删除,不留安全隐患
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
### 11.4 关键信息速查
|
|||
|
|
|
|||
|
|
```
|
|||
|
|
算法:SHA256withRSA
|
|||
|
|
位置:McuM3Update.java:427 / SocUpdate.java:180
|
|||
|
|
格式:固件 + ValidationFile.ini
|
|||
|
|
验证:< 3秒
|
|||
|
|
安全:军工级
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
## 十二、参考文档
|
|||
|
|
|
|||
|
|
- 《RSA2048+SHA256.docx》 - 算法原理说明
|
|||
|
|
- ZipFileVerifier.java - 验证算法实现
|
|||
|
|
- McuM3Update.java - MCU升级流程
|
|||
|
|
- SocUpdate.java - SOC升级流程
|
|||
|
|
- UpdateService.java - 升级服务总控
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
**文档版本**: v1.0
|
|||
|
|
**最后更新**: 2025-05-07
|
|||
|
|
**维护者**: 技术团队
|