[feat] add licence for hfc

This commit is contained in:
zhji 2025-11-30 15:55:22 +08:00
parent ef401f2239
commit 4dc0e91dea
5 changed files with 447 additions and 5 deletions

2
.gitignore vendored
View File

@ -1,4 +1,6 @@
python/*/build/* python/*/build/*
python/*/dist/* python/*/dist/*
python/*/*.spec python/*/*.spec
**/__pycache__/*
python/hfc/测试报告_*.jpg python/hfc/测试报告_*.jpg
python/hfc/license

View File

@ -8,6 +8,13 @@ from PyQt5.QtGui import QPixmap, QFont, QIcon
from pymodbus.client.sync import ModbusSerialClient as ModbusRtuClient from pymodbus.client.sync import ModbusSerialClient as ModbusRtuClient
from pymodbus.exceptions import ModbusException from pymodbus.exceptions import ModbusException
import hashlib
import base64
import uuid
import subprocess
import platform
import logging
class ModbusWorker(QThread): class ModbusWorker(QThread):
"""Modbus通信工作线程""" """Modbus通信工作线程"""
concentration_updated = pyqtSignal(int) # 改为int类型 concentration_updated = pyqtSignal(int) # 改为int类型
@ -210,6 +217,9 @@ class MainWindow(QMainWindow):
} }
""") """)
self.calibrate_button.clicked.connect(self.start_calibration) self.calibrate_button.clicked.connect(self.start_calibration)
if license_check() == False:
self.calibrate_button.setEnabled(False)
self.calibrate_button.setText("许可证无效,请联系管理员")
layout.addWidget(self.calibrate_button) layout.addWidget(self.calibrate_button)
# 状态标签 # 状态标签
@ -245,7 +255,10 @@ class MainWindow(QMainWindow):
def update_concentration(self, concentration): def update_concentration(self, concentration):
"""更新浓度显示""" """更新浓度显示"""
# 直接显示整数,不加小数位 # 直接显示整数,不加小数位
self.concentration_label.setText(f"{concentration} ppm") if license_check():
self.concentration_label.setText(f"{concentration} ppm")
else:
self.concentration_label.setText("许可证无效")
# 根据浓度值改变颜色 # 根据浓度值改变颜色
if concentration < 100: if concentration < 100:
@ -290,6 +303,123 @@ class MainWindow(QMainWindow):
self.modbus_worker.stop() self.modbus_worker.stop()
event.accept() event.accept()
def get_windows_serial_number():
"""
获取Windows系统的唯一序列号
"""
try:
if platform.system() != "Windows":
raise Exception("此功能仅支持Windows系统")
# 使用WMIC获取BIOS序列号
result = subprocess.check_output(
'wmic bios get serialnumber',
shell=True,
stderr=subprocess.STDOUT,
text=True
)
# 解析输出结果
lines = result.strip().split('\n')
for line in lines:
if line.strip() and "SerialNumber" not in line:
serial = line.strip()
if serial and serial != "System Serial Number" and serial != "To be filled by O.E.M.":
return serial
# 如果无法获取BIOS序列号尝试获取磁盘序列号
result = subprocess.check_output(
'wmic diskdrive get serialnumber',
shell=True,
stderr=subprocess.STDOUT,
text=True
)
lines = result.strip().split('\n')
for line in lines:
if line.strip() and "SerialNumber" not in line:
serial = line.strip()
if serial:
return serial
raise Exception("无法获取系统序列号")
except Exception as e:
logging.warning(f"获取Windows序列号失败: {e}")
# 返回一个备用标识符
return str(uuid.getnode())
def get_mac_address():
"""
获取MAC地址
"""
try:
# 获取本机的MAC地址
mac = uuid.getnode()
mac_str = ':'.join(("%012X" % mac)[i:i+2] for i in range(0, 12, 2))
return mac_str
except Exception as e:
logging.error(f"获取MAC地址失败: {e}")
return "00:00:00:00:00:00"
def triple_hash_sha384(data):
"""
对数据进行三次连续的SHA384哈希计算
"""
# 第一次SHA384
hash1 = hashlib.sha384(data.encode('utf-8')).hexdigest()
# 第二次SHA384
hash2 = hashlib.sha384(hash1.encode('utf-8')).hexdigest()
# 第三次SHA384
hash3 = hashlib.sha384(hash2.encode('utf-8')).hexdigest()
return hash3
def triple_hash_sha256(data):
"""
对数据进行三次连续的SHA256哈希计算
"""
# 第一次SHA256
hash1 = hashlib.sha256(data.encode('utf-8')).hexdigest()
# 第二次SHA256
hash2 = hashlib.sha256(hash1.encode('utf-8')).hexdigest()
# 第三次SHA256
hash3 = hashlib.sha256(hash2.encode('utf-8')).hexdigest()
return hash3
def license_check():
"""
j检查证书是否合法
"""
try:
# 0. 读取证书文件
if not os.path.exists('license'):
return False
with open('license', 'r', encoding='utf-8') as f:
existing_license = f.read().strip()
# 1. 获取Windows序列号和MAC地址
serial_number = get_windows_serial_number()
mac_address = get_mac_address()
# 2. 对序列号进行三次SHA384计算
serial_hash = triple_hash_sha384(serial_number)
# 3. 对MAC地址进行三次SHA256计算
mac_hash = triple_hash_sha256(mac_address)
# 4. 拼接两个哈希值并进行Base64编码
combined_hash = serial_hash + mac_hash
base64_encoded = base64.b64encode(combined_hash.encode('utf-8')).decode('utf-8')
# 5. 对Base64结果进行三次SHA384计算
final_hash = triple_hash_sha384(base64_encoded)
# 6. 对最终哈希值进行Base64编码
final_base64 = base64.b64encode(final_hash.encode('utf-8')).decode('utf-8')
# 7. 校验证书合法性
return existing_license == final_base64
except Exception as e:
print(f"\n许可证获取失败: {e}")
return False
if __name__ == "__main__": if __name__ == "__main__":
app = QApplication(sys.argv) app = QApplication(sys.argv)

View File

@ -10,6 +10,13 @@ import struct
from PIL import Image, ImageTk, ImageDraw, ImageFont from PIL import Image, ImageTk, ImageDraw, ImageFont
import os import os
import hashlib
import base64
import uuid
import subprocess
import platform
import logging
class ModbusGasAnalyzer: class ModbusGasAnalyzer:
def __init__(self, root): def __init__(self, root):
self.root = root self.root = root
@ -129,10 +136,17 @@ class ModbusGasAnalyzer:
title_label.pack(pady=40) title_label.pack(pady=40)
# 开始测试按钮 # 开始测试按钮
self.start_button = tk.Button(right_frame, text="开始测试", font=('Arial', 16, 'bold'), if license_check():
bg='green', fg='white', width=15, height=2, self.start_button = tk.Button(right_frame, text="开始测试", font=('Arial', 16, 'bold'),
command=self.start_test) bg='green', fg='white', width=15, height=2,
self.start_button.pack(pady=40) command=self.start_test)
self.start_button.pack(pady=40)
else:
self.start_button = tk.Button(right_frame, text="许可证无效\n请联系管理员", font=('Arial', 16, 'bold'),
bg='green', fg='white', width=15, height=2,
command=self.start_test)
self.start_button.config(state="disable")
self.start_button.pack(pady=40)
def create_page2(self): def create_page2(self):
"""创建第二个页面""" """创建第二个页面"""
@ -595,6 +609,123 @@ class ModbusGasAnalyzer:
return False return False
def get_windows_serial_number():
"""
获取Windows系统的唯一序列号
"""
try:
if platform.system() != "Windows":
raise Exception("此功能仅支持Windows系统")
# 使用WMIC获取BIOS序列号
result = subprocess.check_output(
'wmic bios get serialnumber',
shell=True,
stderr=subprocess.STDOUT,
text=True
)
# 解析输出结果
lines = result.strip().split('\n')
for line in lines:
if line.strip() and "SerialNumber" not in line:
serial = line.strip()
if serial and serial != "System Serial Number" and serial != "To be filled by O.E.M.":
return serial
# 如果无法获取BIOS序列号尝试获取磁盘序列号
result = subprocess.check_output(
'wmic diskdrive get serialnumber',
shell=True,
stderr=subprocess.STDOUT,
text=True
)
lines = result.strip().split('\n')
for line in lines:
if line.strip() and "SerialNumber" not in line:
serial = line.strip()
if serial:
return serial
raise Exception("无法获取系统序列号")
except Exception as e:
logging.warning(f"获取Windows序列号失败: {e}")
# 返回一个备用标识符
return str(uuid.getnode())
def get_mac_address():
"""
获取MAC地址
"""
try:
# 获取本机的MAC地址
mac = uuid.getnode()
mac_str = ':'.join(("%012X" % mac)[i:i+2] for i in range(0, 12, 2))
return mac_str
except Exception as e:
logging.error(f"获取MAC地址失败: {e}")
return "00:00:00:00:00:00"
def triple_hash_sha384(data):
"""
对数据进行三次连续的SHA384哈希计算
"""
# 第一次SHA384
hash1 = hashlib.sha384(data.encode('utf-8')).hexdigest()
# 第二次SHA384
hash2 = hashlib.sha384(hash1.encode('utf-8')).hexdigest()
# 第三次SHA384
hash3 = hashlib.sha384(hash2.encode('utf-8')).hexdigest()
return hash3
def triple_hash_sha256(data):
"""
对数据进行三次连续的SHA256哈希计算
"""
# 第一次SHA256
hash1 = hashlib.sha256(data.encode('utf-8')).hexdigest()
# 第二次SHA256
hash2 = hashlib.sha256(hash1.encode('utf-8')).hexdigest()
# 第三次SHA256
hash3 = hashlib.sha256(hash2.encode('utf-8')).hexdigest()
return hash3
def license_check():
"""
j检查证书是否合法
"""
try:
# 0. 读取证书文件
if not os.path.exists('license'):
return False
with open('license', 'r', encoding='utf-8') as f:
existing_license = f.read().strip()
# 1. 获取Windows序列号和MAC地址
serial_number = get_windows_serial_number()
mac_address = get_mac_address()
# 2. 对序列号进行三次SHA384计算
serial_hash = triple_hash_sha384(serial_number)
# 3. 对MAC地址进行三次SHA256计算
mac_hash = triple_hash_sha256(mac_address)
# 4. 拼接两个哈希值并进行Base64编码
combined_hash = serial_hash + mac_hash
base64_encoded = base64.b64encode(combined_hash.encode('utf-8')).decode('utf-8')
# 5. 对Base64结果进行三次SHA384计算
final_hash = triple_hash_sha384(base64_encoded)
# 6. 对最终哈希值进行Base64编码
final_base64 = base64.b64encode(final_hash.encode('utf-8')).decode('utf-8')
# 7. 校验证书合法性
return existing_license == final_base64
except Exception as e:
print(f"\n许可证获取失败: {e}")
return False
def main(): def main():
root = tk.Tk() root = tk.Tk()
app = ModbusGasAnalyzer(root) app = ModbusGasAnalyzer(root)

View File

@ -0,0 +1,175 @@
import hashlib
import base64
import uuid
import subprocess
import platform
import logging
def get_windows_serial_number():
"""
获取Windows系统的唯一序列号
"""
try:
if platform.system() != "Windows":
raise Exception("此功能仅支持Windows系统")
# 使用WMIC获取BIOS序列号
result = subprocess.check_output(
'wmic bios get serialnumber',
shell=True,
stderr=subprocess.STDOUT,
text=True
)
# 解析输出结果
lines = result.strip().split('\n')
for line in lines:
if line.strip() and "SerialNumber" not in line:
serial = line.strip()
if serial and serial != "System Serial Number" and serial != "To be filled by O.E.M.":
return serial
# 如果无法获取BIOS序列号尝试获取磁盘序列号
result = subprocess.check_output(
'wmic diskdrive get serialnumber',
shell=True,
stderr=subprocess.STDOUT,
text=True
)
lines = result.strip().split('\n')
for line in lines:
if line.strip() and "SerialNumber" not in line:
serial = line.strip()
if serial:
return serial
raise Exception("无法获取系统序列号")
except Exception as e:
logging.warning(f"获取Windows序列号失败: {e}")
# 返回一个备用标识符
return str(uuid.getnode())
def get_mac_address():
"""
获取MAC地址
"""
try:
# 获取本机的MAC地址
mac = uuid.getnode()
mac_str = ':'.join(("%012X" % mac)[i:i+2] for i in range(0, 12, 2))
return mac_str
except Exception as e:
logging.error(f"获取MAC地址失败: {e}")
return "00:00:00:00:00:00"
def triple_hash_sha384(data):
"""
对数据进行三次连续的SHA384哈希计算
"""
print(f"原始数据: {data}")
# 第一次SHA384
hash1 = hashlib.sha384(data.encode('utf-8')).hexdigest()
print(f"第一次SHA384: {hash1}")
# 第二次SHA384
hash2 = hashlib.sha384(hash1.encode('utf-8')).hexdigest()
print(f"第二次SHA384: {hash2}")
# 第三次SHA384
hash3 = hashlib.sha384(hash2.encode('utf-8')).hexdigest()
print(f"第三次SHA384: {hash3}")
return hash3
def triple_hash_sha256(data):
"""
对数据进行三次连续的SHA256哈希计算
"""
print(f"原始数据: {data}")
# 第一次SHA256
hash1 = hashlib.sha256(data.encode('utf-8')).hexdigest()
print(f"第一次SHA256: {hash1}")
# 第二次SHA256
hash2 = hashlib.sha256(hash1.encode('utf-8')).hexdigest()
print(f"第二次SHA256: {hash2}")
# 第三次SHA256
hash3 = hashlib.sha256(hash2.encode('utf-8')).hexdigest()
print(f"第三次SHA256: {hash3}")
return hash3
def main():
"""
主函数
"""
print("=" * 50)
print("开始生成许可证文件")
print("=" * 50)
try:
# 1. 获取Windows序列号和MAC地址
print("\n步骤1: 获取系统信息")
serial_number = get_windows_serial_number()
mac_address = get_mac_address()
print(f"系统序列号: {serial_number}")
print(f"MAC地址: {mac_address}")
# 2. 对序列号进行三次SHA384计算
print("\n步骤2: 对序列号进行三次SHA384计算")
serial_hash = triple_hash_sha384(serial_number)
# 3. 对MAC地址进行三次SHA256计算
print("\n步骤3: 对MAC地址进行三次SHA256计算")
mac_hash = triple_hash_sha256(mac_address)
# 4. 拼接两个哈希值并进行Base64编码
print("\n步骤4: 拼接哈希值并进行Base64编码")
combined_hash = serial_hash + mac_hash
print(f"拼接后的哈希值: {combined_hash}")
base64_encoded = base64.b64encode(combined_hash.encode('utf-8')).decode('utf-8')
print(f"Base64编码结果: {base64_encoded}")
# 5. 对Base64结果进行三次SHA384计算
print("\n步骤5: 对Base64结果进行三次SHA384计算")
final_hash = triple_hash_sha384(base64_encoded)
# 6. 对最终哈希值进行Base64编码
print("\n步骤6: 对最终哈希值进行Base64编码")
final_base64 = base64.b64encode(final_hash.encode('utf-8')).decode('utf-8')
print(f"最终Base64序列: {final_base64}")
# 7. 保存到lic文件
print("\n步骤7: 保存到文件")
with open('license', 'w', encoding='utf-8') as f:
f.write(final_base64)
print(f"许可证文件已保存到: {os.path.abspath('lic')}")
# 8. 成功日志
print("\n" + "=" * 50)
print("许可证生成成功!")
print("=" * 50)
# 显示文件内容预览
print(f"生成的许可证内容 (前50字符): {final_base64[:50]}...")
except Exception as e:
print(f"\n错误: {e}")
logging.error(f"许可证生成失败: {e}")
if __name__ == "__main__":
# 配置日志
logging.basicConfig(level=logging.INFO, format='%(asctime)s - %(levelname)s - %(message)s')
# 导入os模块在需要时导入
import os
main()

View File

@ -1 +1,5 @@
python.exe -m PyInstaller --onefile --windowed --name HFC .\hfc.py python.exe -m PyInstaller --onefile --windowed --name HFC .\hfc.py
python.exe -m PyInstaller --onefile --windowed --name CALI .\cali.py
python.exe -m PyInstaller --onefile --console --name license_generator .\license_generator.py