3. 固件签名生成与验证
任务说明
本案例实现固件签名与验证的最小闭环:使用私钥对固件哈希进行签名,并在设备端使用公钥验证签名,确保固件来源可信且未被篡改。案例基于 Python + cryptography 库,采用 ECDSA P-256 签名算法,完整覆盖密钥生成、签名生成与验签判定三个环节。
环境依赖
- Python 3.8+
- 安装依赖:
pip install cryptography
完整实现代码
from cryptography.hazmat.primitives import hashes, serialization
from cryptography.hazmat.primitives.asymmetric import ec
from cryptography.exceptions import InvalidSignature
import hashlib
# ---------- 1. 密钥生成(实际部署时私钥保存在签名服务器) ----------
def generate_keypair():
private_key = ec.generate_private_key(ec.SECP256R1())
# 私钥序列化(PEM格式)
private_pem = private_key.private_bytes(
encoding=serialization.Encoding.PEM,
format=serialization.PrivateFormat.PKCS8,
encryption_algorithm=serialization.NoEncryption()
)
# 公钥序列化(PEM格式)
public_pem = private_key.public_key().public_bytes(
encoding=serialization.Encoding.PEM,
format=serialization.PublicFormat.SubjectPublicKeyInfo
)
return private_pem, public_pem
# ---------- 2. 固件签名(在签名服务器执行) ----------
def sign_firmware(private_pem, firmware_bytes):
private_key = serialization.load_pem_private_key(private_pem, password=None)
# 计算固件SHA-256哈希
firmware_hash = hashlib.sha256(firmware_bytes).digest()
# 对哈希签名
signature = private_key.sign(firmware_hash, ec.ECDSA(hashes.SHA256()))
return signature
# ---------- 3. 固件验签(在设备端执行) ----------
def verify_firmware(public_pem, firmware_bytes, signature):
public_key = serialization.load_pem_public_key(public_pem)
# 重新计算固件哈希
firmware_hash = hashlib.sha256(firmware_bytes).digest()
try:
public_key.verify(signature, firmware_hash, ec.ECDSA(hashes.SHA256()))
return True
except InvalidSignature:
return False
# ---------- 4. 最小验证闭环 ----------
if __name__ == "__main__":
# 模拟固件数据
firmware = b"\x00\x01\x02\x03\x04\x05\x06\x07\x08\x09" * 100 # 1KB固件
# 生成密钥对
priv_pem, pub_pem = generate_keypair()
# 签名
sig = sign_firmware(priv_pem, firmware)
# 验签(原始固件)
result_ok = verify_firmware(pub_pem, firmware, sig)
print(f"原始固件验签结果: {'通过' if result_ok else '失败'}")
# 验签(篡改固件)
tampered = firmware + b"\xFF"
result_tampered = verify_firmware(pub_pem, tampered, sig)
print(f"篡改固件验签结果: {'通过' if result_tampered else '失败'}")
# 预期输出(确定性结果):
# 原始固件验签结果: 通过
# 篡改固件验签结果: 失败
运行方式
python firmware_sign_verify.py
验证方法与判定标准
- 通过条件:程序输出两行结果,第一行为“原始固件验签结果: 通过”,第二行为“篡改固件验签结果: 失败”。
- 逻辑说明:签名过程对固件哈希(SHA-256)进行ECDSA签名;验签时重新计算哈希并与签名比对。原始固件哈希一致,验签通过;篡改后哈希变化,验签失败。
- 安全边界:本案例演示签名与验签核心流程。实际OTA系统中,私钥应存储在硬件安全模块(HSM)或隔离的签名服务器中,公钥需在设备出厂时安全烧录,防止被替换。
常见问题
- 验签失败:确认公钥与签名所用私钥是否匹配;确认固件字节在签名与验签之间未被修改(包括文件读取时的换行符差异)。
- 算法选择:ECDSA P-256 在资源受限的嵌入式设备上性能优于RSA-2048,且签名长度更短(64字节),适合OTA场景。