2. 升级包完整性校验
任务说明
OTA升级包在下载过程中可能因网络异常、存储介质故障或恶意篡改导致数据不完整。本案例实现一个升级包完整性校验工具,在升级前对升级包文件计算SHA-256哈希值,并与官方发布的基准哈希值比对,一致则允许升级,否则终止升级流程。
环境依赖
- Python 3.8+(标准库,无第三方依赖)
- 操作系统:Linux/Windows/macOS均可
关键完整代码
import hashlib
import sys
import os
import json
def calculate_sha256(file_path, chunk_size=8192):
"""计算文件的SHA-256哈希值,分块读取避免内存占用过高"""
sha256_hash = hashlib.sha256()
try:
with open(file_path, 'rb') as f:
while chunk := f.read(chunk_size):
sha256_hash.update(chunk)
return sha256_hash.hexdigest()
except FileNotFoundError:
return None
except PermissionError:
return None
def verify_package(file_path, expected_hash):
"""
校验升级包完整性
返回: (是否通过, 实际哈希值, 错误信息)
"""
if not os.path.exists(file_path):
return False, None, f"文件不存在: {file_path}"
actual_hash = calculate_sha256(file_path)
if actual_hash is None:
return False, None, "文件读取失败,请检查文件权限"
if actual_hash.lower() == expected_hash.lower():
return True, actual_hash, "校验通过"
else:
return False, actual_hash, "哈希不匹配,文件可能已损坏或被篡改"
def load_expected_hash(manifest_path):
"""从manifest.json中加载期望哈希值"""
try:
with open(manifest_path, 'r', encoding='utf-8') as f:
manifest = json.load(f)
return manifest.get('sha256')
except (FileNotFoundError, json.JSONDecodeError):
return None
def main():
if len(sys.argv) != 3:
print("用法: python verify_ota.py <升级包路径> <manifest.json路径>")
sys.exit(2)
package_path = sys.argv[1]
manifest_path = sys.argv[2]
expected_hash = load_expected_hash(manifest_path)
if expected_hash is None:
print("错误: 无法从manifest.json读取sha256字段")
sys.exit(1)
passed, actual_hash, message = verify_package(package_path, expected_hash)
print(f"期望SHA-256: {expected_hash}")
if actual_hash:
print(f"实际SHA-256: {actual_hash}")
print(f"校验结果: {message}")
if passed:
print("升级包校验通过,允许执行升级流程")
sys.exit(0)
else:
print("升级包校验失败,终止升级流程")
sys.exit(1)
if __name__ == "__main__":
main()
运行与验证
准备测试文件:
# 创建测试升级包和manifest
echo "OTA升级包测试内容 v1.0" > upgrade_package.bin
sha256sum upgrade_package.bin # Linux/Mac
# Windows: certutil -hashfile upgrade_package.bin SHA256
# 将输出的哈希值写入manifest.json
cat > manifest.json << EOF
{"sha256": "上一步计算出的哈希值"}
EOF
运行校验:
python verify_ota.py upgrade_package.bin manifest.json
通过条件:
- 输出“校验通过”,退出码为0
- 篡改测试:修改upgrade_package.bin内容后再次运行,应输出“哈希不匹配”,退出码为1
关键说明
- SHA-256为当前OTA升级校验的主流算法,碰撞概率极低,满足完整性校验需求
- manifest.json由升级服务端在发布时生成,与升级包一同下发或预置于车机安全存储区
- 分块读取(8KB)确保大升级包(数GB)校验时内存占用恒定
- 实际车机集成时,将
verify_package()的返回值作为升级前置条件,校验失败时直接中止升级流程并上报错误码