[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/*/dist/*
python/*/*.spec
**/__pycache__/*
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.exceptions import ModbusException
import hashlib
import base64
import uuid
import subprocess
import platform
import logging
class ModbusWorker(QThread):
"""Modbus通信工作线程"""
concentration_updated = pyqtSignal(int) # 改为int类型
@ -210,6 +217,9 @@ class MainWindow(QMainWindow):
}
""")
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)
# 状态标签
@ -245,7 +255,10 @@ class MainWindow(QMainWindow):
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:
@ -290,6 +303,123 @@ class MainWindow(QMainWindow):
self.modbus_worker.stop()
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__":
app = QApplication(sys.argv)

View File

@ -10,6 +10,13 @@ import struct
from PIL import Image, ImageTk, ImageDraw, ImageFont
import os
import hashlib
import base64
import uuid
import subprocess
import platform
import logging
class ModbusGasAnalyzer:
def __init__(self, root):
self.root = root
@ -129,10 +136,17 @@ class ModbusGasAnalyzer:
title_label.pack(pady=40)
# 开始测试按钮
self.start_button = tk.Button(right_frame, text="开始测试", font=('Arial', 16, 'bold'),
bg='green', fg='white', width=15, height=2,
command=self.start_test)
self.start_button.pack(pady=40)
if license_check():
self.start_button = tk.Button(right_frame, text="开始测试", font=('Arial', 16, 'bold'),
bg='green', fg='white', width=15, height=2,
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):
"""创建第二个页面"""
@ -595,6 +609,123 @@ class ModbusGasAnalyzer:
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():
root = tk.Tk()
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 CALI .\cali.py
python.exe -m PyInstaller --onefile --console --name license_generator .\license_generator.py