概述
在软件开发领域,如何有效防止软件盗版是一个永恒的话题。传统的序列号验证方式容易被破解,而基于硬件指纹的授权系统因其唯一性和不可复制性成为更安全的选择。本文将完整实现一个基于硬件指纹的双向验证系统,包含:
[ol]
[/ol]
系统特点:
功能架构
graph TD
A[硬件信息采集] --> B[主板序列号]
A --> C[CPU标识符]
A --> D[硬盘序列号]
B --> E[硬件码生成]
C --> E
D --> E
E --> F[注册机加密]
F --> G[注册码验证]
️ 效果展示
硬件码生成工具


注册机工作界面


使用教程
硬件码获取步骤
[ol]
[/ol]
注册码生成步骤
[ol]
[/ol]
验证流程

核心代码解析
硬件信息采集(WMI查询)
def get_windows_hardware_info(self):
pythoncom.CoInitialize() # COM库初始化
c = wmi.WMI()
info = {
"motherboard": self._get_board_serial(c),
"cpu": self._get_cpu_id(c),
"disk": self._get_disk_serial(c)
}
pythoncom.CoUninitialize()
return info
多层加密算法
def complex_encryption(self, hw_code):
# 第一层:HMAC-SHA256
hmac_hash = hmac.new(secret_key, hw_bytes, hashlib.sha256).digest()
# 第二层:加盐SHA3
salted_hash = hashlib.sha3_256(hmac_hash + salt).digest()
# 第三层:字节混淆
mixed = bytearray([salted_hash ^ salted_hash[31-i] for i in range(16)])
# 第四层:Base64转换
return hashlib.sha256(base64.b64encode(mixed)).hexdigest()[:32]
关键安全设计
[ol]
[/ol]
源码下载
HardwareValidator.py
import sys
import hmac
import hashlib
import base64
from PyQt5.QtWidgets import (QApplication, QMainWindow, QVBoxLayout, QHBoxLayout,
QWidget, QLabel, QLineEdit, QPushButton, QMessageBox,
QGroupBox, QStatusBar, QSpacerItem, QSizePolicy)
from PyQt5.QtCore import Qt, QTimer
from PyQt5.QtGui import QFont, QPalette, QColor
import wmi
from Crypto.Cipher import AES
from Crypto.Util.Padding import pad
import pythoncom
class HardwareValidator(QMainWindow):
def __init__(self):
super().__init__()
self.setWindowTitle(" 硬件码验证工具")
self.setFixedSize(450, 430)
# 设置主窗口背景色
self.setAutoFillBackground(True)
palette = self.palette()
palette.setColor(QPalette.Window, QColor(240, 240, 240))
self.setPalette(palette)
# Main widget
self.main_widget = QWidget()
self.setCentralWidget(self.main_widget)
# Main layout
self.main_layout = QVBoxLayout()
self.main_layout.setContentsMargins(20, 20, 20, 10)
self.main_layout.setSpacing(15)
self.main_widget.setLayout(self.main_layout)
# Header
self.create_header()
# Hardware code section
self.create_hardware_code_section()
# Registration code section
self.create_registration_section()
# Buttons
self.create_action_buttons()
# Status bar
self.create_status_bar()
# Initialize hardware info
self.hardware_info = {
"motherboard": "unknown",
"cpu": "unknown",
"system_disk": "unknown"
}
# Automatically collect hardware info on startup
QTimer.singleShot(100, self.collect_hardware_info)
def create_header(self):
"""Create the header section"""
header_group = QGroupBox()
header_group.setStyleSheet("""
QGroupBox {
border: 0;
margin-top: 10px;
}
""")
header_layout = QVBoxLayout()
header_layout.setSpacing(10)
title = QLabel(" 硬件码验证工具")
title_font = QFont()
title_font.setPointSize(15)
title_font.setBold(True)
title.setFont(title_font)
title.setAlignment(Qt.AlignCenter)
title.setStyleSheet("color: #2c3e50;")
description = QLabel("本机硬件码已自动生成,请输入注册码完成验证")
description.setAlignment(Qt.AlignCenter)
description.setWordWrap(True)
description.setStyleSheet("color: #7f8c8d; font-size: 12px;")
header_layout.addWidget(title)
header_layout.addWidget(description)
header_group.setLayout(header_layout)
self.main_layout.addWidget(header_group)
def create_hardware_code_section(self):
"""Create the hardware code display section"""
hw_group = QGroupBox("️ 硬件码")
hw_group.setStyleSheet("""
QGroupBox {
border: 1px solid #bdc3c7;
border-radius: 5px;
margin-top: 5px;
padding-top: 15px;
}
QGroupBox::title {
subcontrol-origin: margin;
left: 10px;
padding: 0 3px;
}
""")
hw_layout = QVBoxLayout()
hw_layout.setContentsMargins(10, 15, 10, 15)
self.hw_display = QLineEdit()
self.hw_display.setReadOnly(True)
self.hw_display.setAlignment(Qt.AlignCenter)
self.hw_display.setStyleSheet("""
QLineEdit {
font-size: 14px;
font-family: 'Courier New';
border: 1px solid #bdc3c7;
border-radius: 3px;
padding: 5px;
background-color: #f8f9fa;
}
""")
self.hw_display.setPlaceholderText("正在生成硬件码...")
hw_layout.addWidget(self.hw_display)
hw_group.setLayout(hw_layout)
self.main_layout.addWidget(hw_group)
def create_registration_section(self):
"""Create the registration code input section"""
reg_group = QGroupBox(" 注册码")
reg_group.setStyleSheet("""
QGroupBox {
border: 1px solid #bdc3c7;
border-radius: 5px;
margin-top: 5px;
padding-top: 15px;
}
QGroupBox::title {
subcontrol-origin: margin;
left: 10px;
padding: 0 3px;
}
""")
reg_layout = QVBoxLayout()
reg_layout.setContentsMargins(10, 15, 10, 15)
self.reg_input = QLineEdit()
self.reg_input.setAlignment(Qt.AlignCenter)
self.reg_input.setStyleSheet("""
QLineEdit {
font-size: 14px;
font-family: 'Courier New';
border: 1px solid #bdc3c7;
border-radius: 3px;
padding: 5px;
}
QLineEdit:focus {
border: 1px solid #3498db;
}
""")
self.reg_input.setPlaceholderText("请输入您的注册码...")
reg_layout.addWidget(self.reg_input)
reg_group.setLayout(reg_layout)
self.main_layout.addWidget(reg_group)
def create_action_buttons(self):
"""Create the action buttons"""
button_group = QWidget()
button_layout = QHBoxLayout()
button_layout.setContentsMargins(0, 10, 0, 0)
button_layout.setSpacing(15)
# Copy Hardware Code Button (替换原来的退出按钮)
self.copy_btn = QPushButton("复制硬件码")
self.copy_btn.setStyleSheet("""
QPushButton {
background-color: #3498db;
color: white;
border: none;
border-radius: 5px;
padding: 8px 15px;
font-size: 14px;
}
QPushButton:hover {
background-color: #2980b9;
}
QPushButton:disabled {
background-color: #95a5a6;
}
""")
self.copy_btn.clicked.connect(self.copy_hardware_code)
self.copy_btn.setEnabled(False) # 初始禁用,等硬件码生成后启用
# Register Button
self.register_btn = QPushButton("注册")
self.register_btn.setStyleSheet("""
QPushButton {
background-color: #2ecc71;
color: white;
border: none;
border-radius: 5px;
padding: 8px 25px;
font-size: 14px;
}
QPushButton:hover {
background-color: #27ae60;
}
QPushButton:disabled {
background-color: #95a5a6;
}
""")
self.register_btn.clicked.connect(self.validate)
self.register_btn.setEnabled(False)
button_layout.addWidget(self.copy_btn)
button_layout.addWidget(self.register_btn)
button_group.setLayout(button_layout)
self.main_layout.addWidget(button_group)
def create_status_bar(self):
"""Create the status bar"""
self.status_bar = QStatusBar()
self.status_bar.setStyleSheet("""
QStatusBar {
background-color: #ecf0f1;
color: #7f8c8d;
font-size: 12px;
border-top: 1px solid #bdc3c7;
}
""")
self.setStatusBar(self.status_bar)
self.status_bar.showMessage("正在初始化...", 3000)
def collect_hardware_info(self):
"""Collect hardware information"""
self.status_bar.showMessage("正在收集硬件信息...")
QApplication.processEvents() # Update UI immediately
try:
self.hardware_info = self.get_windows_hardware_info()
# Generate hardware code automatically
hardware_code = self.generate_hardware_code_internal(self.hardware_info)
# Display the hardware code
self.hw_display.setText(hardware_code)
# Enable buttons
self.register_btn.setEnabled(True)
self.copy_btn.setEnabled(True)
self.status_bar.showMessage("就绪,请输入注册码", 3000)
except Exception as e:
self.status_bar.showMessage(f"错误: {str(e)}", 5000)
QMessageBox.critical(self, "错误", f"收集硬件信息时出错:\n{str(e)}")
def get_windows_hardware_info(self):
"""获取Windows硬件信息"""
pythoncom.CoInitialize() # 初始化COM库
c = wmi.WMI()
hardware_info = {
"motherboard": "unknown",
"cpu": "unknown",
"system_disk": "unknown"
}
try:
# 获取主板序列号
for board in c.Win32_BaseBoard():
if board.SerialNumber and board.SerialNumber.strip() != "":
hardware_info["motherboard"] = board.SerialNumber.strip()
break
# 获取CPU序列号
for cpu in c.Win32_Processor():
if cpu.ProcessorId and cpu.ProcessorId.strip() != "":
hardware_info["cpu"] = cpu.ProcessorId.strip()
break
# 获取系统盘序列号(C盘所在的物理磁盘)
for partition in c.Win32_DiskPartition():
if partition.BootPartition:
for disk in c.Win32_DiskDrive(Index=partition.DiskIndex):
if disk.SerialNumber and disk.SerialNumber.strip() != "":
hardware_info["system_disk"] = disk.SerialNumber.strip()
break
break
# 如果上述方法失败,尝试另一种获取系统盘的方法
if hardware_info["system_disk"] == "unknown":
for disk in c.Win32_DiskDrive():
if disk.SerialNumber and disk.SerialNumber.strip() != "":
for link in disk.associators("Win32_DiskDriveToDiskPartition"):
for partition in link.associators("Win32_LogicalDiskToPartition"):
if partition.DeviceID == "C:":
hardware_info["system_disk"] = disk.SerialNumber.strip()
break
if hardware_info["system_disk"] != "unknown":
break
except Exception as e:
raise Exception(f"获取硬件信息时出错: {e}")
finally:
pythoncom.CoUninitialize() # 释放COM库
return hardware_info
def generate_hardware_code_internal(self, hardware_info):
"""生成32位硬件码"""
# 组合硬件信息并添加盐值增加复杂度
combined = (
f"{hardware_info['motherboard']}"
f"{hardware_info['cpu']}"
f"{hardware_info['system_disk']}"
"SALT_VALUE_123!" # 自定义盐值
)
# 使用SHA-256生成固定长度的哈希值
hash_obj = hashlib.sha256(combined.encode('utf-8'))
hash_digest = hash_obj.digest()
# AES加密(使用哈希值的前16字节作为密钥)
key = hash_digest[:16]
cipher = AES.new(key, AES.MODE_ECB)
# 对哈希值自身进行加密
encrypted = cipher.encrypt(pad(hash_digest, AES.block_size))
# 转换为32字符的十六进制字符串(不含分隔符)
hardware_code = encrypted.hex()[:32].upper()
return hardware_code
def copy_hardware_code(self):
"""复制硬件码到剪贴板"""
hw_code = self.hw_display.text()
if hw_code:
clipboard = QApplication.clipboard()
clipboard.setText(hw_code)
self.status_bar.showMessage("硬件码已复制到剪贴板", 3000)
QMessageBox.information(self, "复制成功", "✅ 硬件码已复制到剪贴板!")
else:
self.status_bar.showMessage("无有效的硬件码可复制", 3000)
def complex_encryption(self, hw_code):
"""注册码加密算法实现"""
secret_key = b"x7F!pL9#qR2sT5*uV8%wY3zA6&dC4"
hw_bytes = hw_code.encode('utf-8')
hmac_hash = hmac.new(secret_key, hw_bytes, hashlib.sha256).digest()
salt = b"kP6@mN1$jK4^bH7&vG2*lP9"
salted_hash = hashlib.sha3_256(hmac_hash + salt).digest()
mixed = bytearray()
for i in range(16):
mixed.append(salted_hash ^ salted_hash[31 - i])
b64 = base64.b64encode(mixed).decode('utf-8')[:32]
final = hashlib.sha256(b64.encode('utf-8')).hexdigest()[:32]
return final.upper()
def validate_hardware_code(self, code):
"""验证硬件码格式"""
clean_code = code.strip().upper().replace('-', '')
return len(clean_code) == 32 and all(c in '0123456789ABCDEF' for c in clean_code)
def validate(self):
"""验证注册码"""
hw_code = self.hw_display.text().strip()
reg_code = self.reg_input.text().strip()
if not self.validate_hardware_code(hw_code):
self.show_error("无效的硬件码", "硬件码格式不正确")
return
clean_hw = hw_code.upper().replace('-', '')
clean_reg = reg_code.upper().replace('-', '')
if len(clean_reg) != 32 or not all(c in '0123456789ABCDEF' for c in clean_reg):
self.show_error("无效的注册码", "注册码应为32位十六进制字符")
return
try:
correct_reg = self.complex_encryption(clean_hw)
if clean_reg == correct_reg:
self.status_bar.showMessage("验证通过!注册成功", 5000)
QMessageBox.information(self, "验证成功", "✅ 注册码验证通过!")
else:
self.status_bar.showMessage("验证失败!注册码无效", 5000)
QMessageBox.warning(self, "验证失败", "❌ 输入的注册码与硬件码不匹配")
except Exception as e:
self.show_error("验证错误", f"验证过程中发生错误:\n{str(e)}")
def show_error(self, title, message):
"""显示错误消息"""
self.status_bar.showMessage("错误: " + message.split('\n')[0], 5000)
QMessageBox.critical(self, title, message)
if __name__ == "__main__":
# Check dependencies before starting the app
try:
import wmi
from Crypto.Cipher import AES
app = QApplication(sys.argv)
app.setStyle('Fusion')
# Set application font
font = QFont()
font.setFamily("Microsoft YaHei" if sys.platform == "win32" else "Arial")
font.setPointSize(10)
app.setFont(font)
window = HardwareValidator()
window.show()
sys.exit(app.exec_())
except ImportError as e:
print(f"缺少必要依赖库: {e}")
print("请安装以下库:")
print("1. pywin32 (用于WMI访问): pip install pywin32")
print("2. pycryptodome (用于AES加密): pip install pycryptodome")
input("按Enter键退出...")
RegistrationGenerator.py
import sys
import hashlib
from PyQt5.QtWidgets import (QApplication, QMainWindow, QLabel, QLineEdit,
QPushButton, QVBoxLayout, QWidget, QMessageBox)
from PyQt5.QtCore import Qt, QTimer
import secrets
import hmac
import base64
class RegistrationGenerator(QMainWindow):
def __init__(self):
super().__init__()
self.setWindowTitle(" 硬件码注册机")
self.setGeometry(300, 300, 350, 300)
# 设置主窗口部件
self.central_widget = QWidget()
self.setCentralWidget(self.central_widget)
# 创建布局
self.layout = QVBoxLayout()
self.central_widget.setLayout(self.layout)
# 添加UI元素
self.create_ui()
def create_ui(self):
# 标题
title = QLabel("✨ 32位硬件码注册机 ✨")
title.setAlignment(Qt.AlignCenter)
title.setStyleSheet("font-size: 20px; font-weight: bold; margin-bottom: 20px;")
self.layout.addWidget(title)
# 硬件码输入
hw_label = QLabel(" 请输入32位硬件码:")
self.hw_input = QLineEdit()
self.hw_input.setPlaceholderText("请输入32位十六进制硬件码...")
self.hw_input.setMaxLength(32)
self.layout.addWidget(hw_label)
self.layout.addWidget(self.hw_input)
# 注册码显示
reg_label = QLabel(" 生成的32位注册码:")
self.reg_output = QLineEdit()
self.reg_output.setReadOnly(True)
self.reg_output.setPlaceholderText("注册码将在这里显示...")
self.layout.addWidget(reg_label)
self.layout.addWidget(self.reg_output)
# 生成按钮
self.generate_btn = QPushButton(" 生成注册码")
self.generate_btn.setStyleSheet("background-color: #4CAF50; color: white; padding: 10px;")
self.generate_btn.clicked.connect(self.generate_reg_code)
self.layout.addWidget(self.generate_btn)
# 复制按钮
self.copy_btn = QPushButton(" 复制注册码")
self.copy_btn.setStyleSheet("background-color: #2196F3; color: white; padding: 10px;")
self.copy_btn.clicked.connect(self.copy_to_clipboard)
self.layout.addWidget(self.copy_btn)
# 底部信息
footer = QLabel(" 提示: 请确保输入的硬件码是32位十六进制字符")
footer.setAlignment(Qt.AlignCenter)
footer.setStyleSheet("font-size: 12px; color: #666; margin-top: 20px;")
self.layout.addWidget(footer)
def validate_hardware_code(self, code):
"""验证硬件码是否为有效的32位十六进制字符串"""
if len(code) != 32:
return False
try:
int(code, 16)
return True
except ValueError:
return False
def complex_encryption(self, hw_code):
"""复杂的加密算法生成注册码"""
# 使用HMAC-SHA256作为基础
secret_key = b"x7F!pL9#qR2sT5*uV8%wY3zA6&dC4"
hw_bytes = hw_code.encode('utf-8')
# 第一层加密: HMAC-SHA256
hmac_hash = hmac.new(secret_key, hw_bytes, hashlib.sha256).digest()
# 第二层加密: 带盐的SHA3_256
salt = b"kP6@mN1$jK4^bH7&vG2*lP9"
salted_hash = hashlib.sha3_256(hmac_hash + salt).digest()
# 第三层加密: 自定义混淆
mixed = bytearray()
for i in range(16):
mixed.append(salted_hash ^ salted_hash[31 - i])
# 转换为base64并取特定部分
b64 = base64.b64encode(mixed).decode('utf-8')[:32]
# 确保输出是32位十六进制
final = hashlib.sha256(b64.encode('utf-8')).hexdigest()[:32]
return final.upper()
def generate_reg_code(self):
hw_code = self.hw_input.text().strip()
if not self.validate_hardware_code(hw_code):
QMessageBox.warning(self, "⚠️ 输入错误",
"请输入有效的32位十六进制硬件码!\n(例如: 5A3B7C9D2E1F4G6H8J0K2L4M6N8P0Q2)")
return
reg_code = self.complex_encryption(hw_code)
# 修改这里:将注册码格式化为4位一组,用"-"隔开
formatted_reg = '-'.join([reg_code[i:i+4] for i in range(0, 32, 4)])
self.reg_output.setText(formatted_reg)
QMessageBox.information(self, "✅ 成功", "注册码已生成!")
def copy_to_clipboard(self):
reg_code = self.reg_output.text()
if not reg_code:
QMessageBox.warning(self, "⚠️ 错误", "没有可复制的注册码!")
return
clipboard = QApplication.clipboard()
clipboard.setText(reg_code)
if __name__ == "__main__":
app = QApplication(sys.argv)
# 设置全局字体和样式
app.setStyleSheet("""
QWidget {
font-family: 'Arial';
}
QLineEdit {
padding: 8px;
border: 1px solid #ccc;
border-radius: 4px;
}
QPushButton:hover {
opacity: 0.9;
}
""")
window = RegistrationGenerator()
window.show()
sys.exit(app.exec_())
再补充一部分将注册码保存到注册表验证的部分实现代码(实现检测到注册表有对应注册码则跳过注册页面,否则需要先注册)
class RegistrationManager:
"""注册信息管理类"""
REG_KEY = r"SOFTWARE\NASDriveMapper"
REG_VALUE_NAME = "RegistrationInfo"
@classmethod
def save_registration(cls, hw_code, reg_code):
"""保存注册信息到注册表"""
try:
# 创建或打开注册表键
key = winreg.CreateKey(winreg.HKEY_CURRENT_USER, cls.REG_KEY)
# 将硬件码和注册码组合后存储
combined = f"{hw_code}:{reg_code}"
winreg.SetValueEx(key, cls.REG_VALUE_NAME, 0, winreg.REG_SZ, combined)
winreg.CloseKey(key)
return True
except Exception as e:
print(f"保存注册信息失败: {e}")
return False
@classmethod
def load_registration(cls):
"""从注册表加载注册信息"""
try:
key = winreg.OpenKey(winreg.HKEY_CURRENT_USER, cls.REG_KEY, 0, winreg.KEY_READ)
value, _ = winreg.QueryValueEx(key, cls.REG_VALUE_NAME)
winreg.CloseKey(key)
return value.split(":")
except Exception:
return None
@classmethod
def validate_stored_registration(cls, hw_code, validator_func):
"""验证注册表中存储的注册信息"""
stored = cls.load_registration()
if not stored or len(stored) != 2:
return False
stored_hw, stored_reg = stored
correct_reg = validator_func(hw_code)
return stored_hw == hw_code and stored_reg == correct_reg
# 安装依赖
pip install -r requirements.txt
# 运行硬件工具
python HardwareValidator.py
# 运行注册机
python RegistrationGenerator.py
附件源码链接如下:https://wwgt.lanzoum.com/ilMsP33zjvah