# client.py - RK3588板端激活程序(永久有效) import os import sys import json import hashlib import hmac import requests import subprocess import time import logging import argparse from datetime import datetime # 配置日志 logging.basicConfig( level=logging.INFO, format='%(asctime)s - %(levelname)s - %(message)s' ) logger = logging.getLogger(__name__) # 配置 CONFIG = { 'SERVER_URL': 'http://129.211.170.245:5000/', # 修改为实际服务器地址 'KEY_FILE': '/etc/device.key', # 密钥文件存储路径 'KEY_BACKUP_FILE': '/etc/device.key.bak', # 密钥备份文件 'CHIP_ID_SOURCES': [ '/sys/devices/soc0/serial_number', '/sys/devices/platform/ff650000.serial/serial0', '/proc/cpuinfo' ], 'ACTIVATE_URL': '/activate', 'VERIFY_URL': '/verify', 'ACTIVATE_RETRY_COUNT': 3, 'SECRET_KEY': '69588cc5e1b701942cda09b33de5a95c02471f3aaaf610d80aaf5681f4b166e4' # 必须和服务端一致 } def get_chip_id(): """ 获取RK3588芯片ID(增强版) """ # 方法1: 从多个系统文件读取 for source in CONFIG['CHIP_ID_SOURCES']: try: if os.path.exists(source): with open(source, 'r') as f: content = f.read().strip() # 处理cpuinfo的特殊格式 if source == '/proc/cpuinfo': for line in content.split('\n'): if 'Serial' in line: chip_id = line.split(':')[1].strip() if chip_id: logger.info(f"从{source}获取芯片ID: {chip_id}") return chip_id else: if content: logger.info(f"从{source}获取芯片ID: {content}") return content except Exception as e: logger.warning(f"读取{source}失败: {e}") # 方法2: 使用dmidecode命令 try: result = subprocess.run( ['dmidecode', '-s', 'system-serial-number'], capture_output=True, text=True, timeout=5 ) if result.returncode == 0 and result.stdout.strip(): chip_id = result.stdout.strip() logger.info(f"从dmidecode获取芯片ID: {chip_id}") return chip_id except Exception as e: logger.warning(f"执行dmidecode失败: {e}") # 方法3: 读取MAC地址 try: import uuid mac = uuid.UUID(int=uuid.getnode()).hex[-12:] chip_id = f"MAC-{mac}" logger.warning(f"使用MAC地址生成ID: {chip_id}") return chip_id except Exception as e: logger.error(f"无法获取任何标识: {e}") return None def verify_key_signature(chip_id, key_data): """ 验证密钥签名(永久有效) """ try: # 构建待签名数据 data_to_sign = f"{chip_id}|{key_data['activation_id']}|{key_data['activate_time']}" # 计算期望的签名 expected_signature = hmac.new( CONFIG['SECRET_KEY'].encode('utf-8'), data_to_sign.encode('utf-8'), hashlib.sha256 ).hexdigest() # 比对签名 if key_data['signature'] != expected_signature: logger.error("密钥签名验证失败") return False, "密钥签名无效" logger.info("密钥签名验证通过") return True, "签名验证通过" except Exception as e: logger.error(f"签名验证异常: {e}") return False, f"验证异常: {str(e)}" def save_key_file(key_data): """ 保存密钥文件到本地(永久有效) """ try: # 确保目录存在 key_dir = os.path.dirname(CONFIG['KEY_FILE']) if key_dir and not os.path.exists(key_dir): os.makedirs(key_dir, exist_ok=True) # 如果已有密钥文件,先备份 if os.path.exists(CONFIG['KEY_FILE']): import shutil shutil.copy2(CONFIG['KEY_FILE'], CONFIG['KEY_BACKUP_FILE']) logger.info(f"已备份旧密钥文件到: {CONFIG['KEY_BACKUP_FILE']}") # 保存新密钥文件 with open(CONFIG['KEY_FILE'], 'w') as f: json.dump(key_data, f, indent=2) # 设置文件权限为只读 os.chmod(CONFIG['KEY_FILE'], 0o600) logger.info(f"密钥文件已保存: {CONFIG['KEY_FILE']}") return True except Exception as e: logger.error(f"保存密钥文件失败: {e}") return False def load_key_file(): """ 加载本地密钥文件 """ try: # 尝试加载主密钥文件 if os.path.exists(CONFIG['KEY_FILE']): with open(CONFIG['KEY_FILE'], 'r') as f: key_data = json.load(f) logger.info("密钥文件加载成功") return key_data # 尝试加载备份密钥文件 if os.path.exists(CONFIG['KEY_BACKUP_FILE']): logger.warning("主密钥文件不存在,尝试加载备份") with open(CONFIG['KEY_BACKUP_FILE'], 'r') as f: key_data = json.load(f) logger.info("备份密钥文件加载成功") return key_data logger.warning("密钥文件不存在") return None except Exception as e: logger.error(f"加载密钥文件失败: {e}") return None def verify_local_key(chip_id): """ 本地验证密钥(永久有效,无过期检查) """ # 加载密钥文件 key_data = load_key_file() if not key_data: return False, "密钥文件不存在" # 验证芯片ID是否匹配 if key_data.get('chip_id') != chip_id: logger.error(f"芯片ID不匹配: 期望 {key_data.get('chip_id')}, 实际 {chip_id}") return False, "芯片ID不匹配" # 验证签名 valid, message = verify_key_signature(chip_id, key_data) if not valid: return False, message # 验证通过 logger.info(f"永久激活验证通过!") logger.info(f"激活时间: {key_data['activate_time']}") logger.info(f"激活ID: {key_data['activation_id']}") return True, "验证通过(永久有效)" def activate_device(chip_id): """ 联网激活设备(永久激活) """ url = f"{CONFIG['SERVER_URL']}{CONFIG['ACTIVATE_URL']}" payload = {'chip_id': chip_id} for attempt in range(CONFIG['ACTIVATE_RETRY_COUNT']): try: logger.info(f"正在激活设备 (尝试 {attempt + 1}/{CONFIG['ACTIVATE_RETRY_COUNT']})...") response = requests.post( url, json=payload, timeout=10, headers={'Content-Type': 'application/json'} ) if response.status_code == 200: data = response.json() if data.get('code') == 200: # 保存密钥文件 key_data = data['data'] if save_key_file(key_data): logger.info("设备永久激活成功!") return True else: logger.error("保存密钥文件失败") else: logger.error(f"激活失败: {data.get('message')}") else: logger.error(f"HTTP错误: {response.status_code}") except requests.exceptions.RequestException as e: logger.error(f"网络错误: {e}") except Exception as e: logger.error(f"激活过程中发生错误: {e}") if attempt < CONFIG['ACTIVATE_RETRY_COUNT'] - 1: wait_time = 2 ** attempt logger.info(f"等待 {wait_time} 秒后重试...") time.sleep(wait_time) return False def create_emergency_key(chip_id): """ 创建应急密钥(当无法联网时使用,需人工授权) 警告:此功能仅用于紧急情况 """ import secrets logger.warning("正在创建应急密钥...") # 生成应急密钥数据 emergency_key = { 'chip_id': chip_id, 'activation_id': f"EMERGENCY-{secrets.token_hex(8)}", 'activate_time': datetime.now().strftime('%Y-%m-%d %H:%M:%S'), 'signature': 'EMERGENCY-MODE', # 应急模式签名 'permanent': True, 'emergency': True, 'version': '1.0' } # 保存应急密钥 if save_key_file(emergency_key): logger.warning("应急密钥已创建!请确保这是授权操作!") return True return False def main(): """ 主函数:程序启动验证(永久有效) """ parser = argparse.ArgumentParser(description='设备永久激活和验证程序') parser.add_argument('--force-activate', action='store_true', help='强制重新激活') parser.add_argument('--check-only', action='store_true', help='仅检查验证状态') parser.add_argument('--emergency', action='store_true', help='创建应急密钥(仅限授权使用)') parser.add_argument('--show-info', action='store_true', help='显示激活信息') args = parser.parse_args() # 获取芯片ID chip_id = get_chip_id() if not chip_id: logger.error("无法获取芯片ID") sys.exit(1) logger.info(f"芯片ID: {chip_id}") # 应急模式 if args.emergency: if create_emergency_key(chip_id): logger.info("应急密钥创建成功") sys.exit(0) else: logger.error("应急密钥创建失败") sys.exit(1) # 显示激活信息 if args.show_info: key_data = load_key_file() if key_data: print("\n" + "="*50) print("设备激活信息") print("="*50) print(f"芯片ID: {key_data.get('chip_id')}") print(f"激活时间: {key_data.get('activate_time')}") print(f"激活ID: {key_data.get('activation_id')}") print(f"激活类型: {'永久有效' if key_data.get('permanent') else '临时'}") if key_data.get('emergency'): print("警告: 应急模式激活") print("="*50) else: print("设备未激活") sys.exit(0) # 检查是否需要激活 need_activate = args.force_activate if not need_activate: # 尝试本地验证 valid, message = verify_local_key(chip_id) if valid: logger.info(f"✅ 验证成功: {message}") if not args.check_only: logger.info("验证通过,启动主程序...") # 在这里调用你的主程序 # subprocess.run(['python3', 'your_main_program.py']) sys.exit(0) else: logger.warning(f"❌ 本地验证失败: {message}") need_activate = True # 需要联网激活 if need_activate: logger.info("开始联网永久激活...") if activate_device(chip_id): # 激活后再次验证 valid, message = verify_local_key(chip_id) if valid: logger.info(f"✅ 激活验证成功: {message}") logger.info("设备已永久激活,无需再次联网!") if not args.check_only: logger.info("激活完成,启动主程序...") # subprocess.run(['python3', 'your_main_program.py']) sys.exit(0) else: logger.error(f"❌ 激活后验证失败: {message}") sys.exit(1) else: logger.error("设备激活失败,请检查网络连接") sys.exit(1) def install_service(): """ 安装为系统服务 """ service_content = """[Unit] Description=Device Permanent Activation Check Service After=network.target [Service] Type=oneshot ExecStart=/usr/bin/python3 /opt/device_activation/client.py --check-only RemainAfterExit=yes [Install] WantedBy=multi-user.target """ service_file = '/etc/systemd/system/device-activation.service' try: # 复制程序到系统目录 script_dir = '/opt/device_activation' os.makedirs(script_dir, exist_ok=True) import shutil shutil.copy2(__file__, os.path.join(script_dir, 'client.py')) os.chmod(os.path.join(script_dir, 'client.py'), 0o755) # 创建服务文件 with open(service_file, 'w') as f: f.write(service_content) os.chmod(service_file, 0o644) logger.info(f"服务文件已创建: {service_file}") logger.info("请执行以下命令启用服务:") logger.info("sudo systemctl daemon-reload") logger.info("sudo systemctl enable device-activation.service") logger.info("sudo systemctl start device-activation.service") except Exception as e: logger.error(f"安装服务失败: {e}") if __name__ == '__main__': if len(sys.argv) > 1 and sys.argv[1] == 'install-service': install_service() else: main()