100 lines
3.7 KiB
Python
100 lines
3.7 KiB
Python
# -*- 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文件开头,增加固定长度256(RSA) + 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) # 验签
|