4G_module/tools/scripts/PackageSign.py

100 lines
3.7 KiB
Python
Raw Normal View History

2024-09-02 17:54:29 +08:00
# -*- coding: utf-8 -*-
# ===================================================================
#
# Copyright © 2022 China Mobile IOT. All rights reserved.
#
# Date: 2022/08/05
# Author: zhangxw
# Function: 固件签名
#
# 签名流程①提取bin文件md5码②对md5码进行RSA签名pkcs1_15填充③将签名结果及md5码放置于bin文件开头增加固定长度256RSA + 16(MD5)
# 秘钥存储:公钥存储在模组中,私钥存储在编译环境中
#
# ===================================================================
import sys
import os.path
from Crypto.Signature import pkcs1_15
from Crypto.Hash import MD5
from Crypto.PublicKey import RSA
# 功能:固件签名
# private_key_fn 私钥文件
# bin_fn 待签名文件
# sign_fn 签名后文件
def package_sign(private_key_fn, bin_fn, sign_fn):
with open(private_key_fn) as private_key_file, \
open(bin_fn, "rb") as bin_file, \
open(sign_fn, "wb") as sign_file:
private_key = RSA.import_key(private_key_file.read())
bin_data = bin_file.read()
digest = MD5.new(bin_data) # 生成16字节MD5码
print("MD5:", digest.digest())
# 使用私钥对HASH值进行签名
signature = pkcs1_15.new(private_key).sign(digest) # 私钥签名
sign_file.write(signature) # 写入256字节签名信息
sign_file.write(digest.digest()) # 写入16字节MD5信息
sign_file.write(bin_data) # 写入固件信息
return signature
# 功能:固件验签
# public_key_fn 公钥文件
# sign_fn 签名固件
def package_check(public_key_fn, sign_fn):
with open(public_key_fn) as public_key_file, \
open(sign_fn, "rb") as sign_file:
public_key = RSA.import_key(public_key_file.read())
sign_data = sign_file.read(256) # 读取签名信息
sign_file.read(16) # 读取MD5信息
bin_data = sign_file.read() # 读取固件信息
md5_data = MD5.new(bin_data)
# print(sign_data)
print("MD5:", md5_data.digest())
try:
pkcs1_15.new(public_key).verify(md5_data, sign_data)
print("签名验证成功!!!")
except:
print("签名验证失败!!!")
# 功能:生成公私秘钥对
def pem_generate(length):
key = RSA.generate(length)
private_key = key.export_key()
public_key = key.publickey().export_key()
with open("private_key.rsa", "wb") as pri_file, \
open("public_key.rsa", "wb") as pub_file:
pri_file.write(private_key)
pub_file.write(public_key)
# 传入待签名文件,在同一个文件夹下生成签名后文件
if __name__ == "__main__":
if len(sys.argv) != 3:
print("参数错误:", len(sys.argv))
sys.exit()
bin_filename = str(sys.argv[1])
private_key_filename = str(sys.argv[2])
if os.path.isfile(bin_filename) is not True: # 判断bin文件是否存在
print("bin文件不存在", bin_filename)
sys.exit()
if os.path.isfile(private_key_filename) is not True: # 判断私钥文件是否存在
print("私钥文件不存在", private_key_filename)
sys.exit()
bin_dir = os.path.dirname(os.path.realpath(bin_filename))
bin_name = os.path.basename(bin_filename)
sign_bin_file_name = bin_dir + "\sign_" + bin_name # 签名后的文件名
print("开始签名,文件名:", bin_name)
# 将会在bin文件开头增加272固定长度包括256bytes的签名信息及16bytes的md5信息
sign = package_sign(private_key_filename, bin_filename, sign_bin_file_name) # 生成签名包
# print("签名信息:", sign)
print("签名完成,文件名:", sign_bin_file_name)
# package_check("public_key.rsa", sign_bin_file_name) # 验签