""" Hardware Fingerprint Generator fuer die Lizenzierung. Erstellt einen eindeutigen Hardware-Hash basierend auf System-Eigenschaften. """ import hashlib import platform import socket import uuid import os import subprocess import logging from typing import List, Optional logger = logging.getLogger("hardware_fingerprint") class HardwareFingerprint: """Generiert und verwaltet Hardware-Fingerprints f�r die Lizenzierung.""" FINGERPRINT_FILE = os.path.join("config", ".hardware_id") def __init__(self): """Initialisiert den Fingerprint-Generator.""" os.makedirs("config", exist_ok=True) def get_mac_address(self) -> Optional[str]: """ Holt die MAC-Adresse der prim�ren Netzwerkkarte. Returns: MAC-Adresse als String oder None """ try: # UUID-basierte MAC-Adresse (funktioniert cross-platform) mac = ':'.join(['{:02x}'.format((uuid.getnode() >> ele) & 0xff) for ele in range(0,8*6,8)][::-1]) if mac != "00:00:00:00:00:00": return mac except Exception as e: logger.warning(f"Fehler beim Abrufen der MAC-Adresse: {e}") return None def get_cpu_info(self) -> str: """ Holt CPU-Informationen. Returns: CPU-Info als String """ try: # Platform-unabh�ngige CPU-Info cpu_info = platform.processor() if not cpu_info: cpu_info = platform.machine() return cpu_info or "unknown" except Exception as e: logger.warning(f"Fehler beim Abrufen der CPU-Info: {e}") return "unknown" def get_system_uuid(self) -> Optional[str]: """ Versucht die System-UUID zu ermitteln. Returns: System-UUID als String oder None """ try: # Windows if platform.system() == "Windows": try: output = subprocess.check_output( "wmic csproduct get UUID", shell=True, stderr=subprocess.DEVNULL ).decode() lines = output.strip().split('\n') if len(lines) > 1: uuid_str = lines[1].strip() if uuid_str and uuid_str != "FFFFFFFF-FFFF-FFFF-FFFF-FFFFFFFFFFFF": return uuid_str except: pass # Linux elif platform.system() == "Linux": try: with open("/sys/class/dmi/id/product_uuid", "r") as f: uuid_str = f.read().strip() if uuid_str: return uuid_str except: pass # Alternative f�r Linux try: with open("/etc/machine-id", "r") as f: return f.read().strip() except: pass # macOS elif platform.system() == "Darwin": try: output = subprocess.check_output( ["ioreg", "-rd1", "-c", "IOPlatformExpertDevice"], stderr=subprocess.DEVNULL ).decode() for line in output.split('\n'): if 'IOPlatformUUID' in line: uuid_str = line.split('"')[-2] if uuid_str: return uuid_str except: pass except Exception as e: logger.warning(f"Fehler beim Abrufen der System-UUID: {e}") return None def get_disk_serial(self) -> Optional[str]: """ Versucht die Seriennummer der Systemfestplatte zu ermitteln. Returns: Disk Serial als String oder None """ try: if platform.system() == "Windows": try: output = subprocess.check_output( "wmic diskdrive get serialnumber", shell=True, stderr=subprocess.DEVNULL ).decode() lines = output.strip().split('\n') for line in lines[1:]: serial = line.strip() if serial and serial != "SerialNumber": return serial except: pass elif platform.system() == "Linux": try: # Versuche verschiedene Methoden for device in ["/dev/sda", "/dev/nvme0n1", "/dev/vda"]: if os.path.exists(device): try: output = subprocess.check_output( ["sudo", "hdparm", "-I", device], stderr=subprocess.DEVNULL ).decode() for line in output.split('\n'): if 'Serial Number:' in line: return line.split(':')[1].strip() except: pass except: pass except Exception as e: logger.warning(f"Fehler beim Abrufen der Disk-Serial: {e}") return None def generate_hardware_hash(self) -> str: """ Generiert einen eindeutigen Hardware-Hash basierend auf verschiedenen System-Eigenschaften. Returns: Hardware-Hash als String """ components = [] # 1. Hostname (immer verf�gbar) hostname = socket.gethostname() components.append(f"HOST:{hostname}") # 2. MAC-Adresse mac = self.get_mac_address() if mac: components.append(f"MAC:{mac}") # 3. CPU-Info cpu = self.get_cpu_info() components.append(f"CPU:{cpu}") # 4. System-UUID sys_uuid = self.get_system_uuid() if sys_uuid: components.append(f"UUID:{sys_uuid}") # 5. Disk Serial disk_serial = self.get_disk_serial() if disk_serial: components.append(f"DISK:{disk_serial}") # 6. Platform-Info components.append(f"PLATFORM:{platform.system()}-{platform.machine()}") # 7. Username (als Fallback) try: username = os.getlogin() components.append(f"USER:{username}") except: pass # Kombiniere alle Komponenten fingerprint_data = "|".join(sorted(components)) # Erstelle SHA256 Hash hash_object = hashlib.sha256(fingerprint_data.encode()) hardware_hash = hash_object.hexdigest() logger.info(f"Hardware-Fingerprint generiert mit {len(components)} Komponenten") logger.debug(f"Komponenten: {components}") return hardware_hash def get_or_create_fingerprint(self) -> str: """ Holt den gespeicherten Fingerprint oder erstellt einen neuen. Returns: Hardware-Fingerprint als String """ # Pr�fe ob bereits ein Fingerprint existiert if os.path.exists(self.FINGERPRINT_FILE): try: with open(self.FINGERPRINT_FILE, 'r') as f: stored_hash = f.read().strip() if stored_hash: logger.info("Gespeicherten Hardware-Fingerprint gefunden") return stored_hash except Exception as e: logger.warning(f"Fehler beim Lesen des gespeicherten Fingerprints: {e}") # Generiere neuen Fingerprint hardware_hash = self.generate_hardware_hash() # Speichere f�r zuk�nftige Verwendung try: with open(self.FINGERPRINT_FILE, 'w') as f: f.write(hardware_hash) logger.info("Hardware-Fingerprint gespeichert") except Exception as e: logger.error(f"Fehler beim Speichern des Fingerprints: {e}") return hardware_hash def get_machine_name(self) -> str: """ Gibt den Maschinennamen zur�ck. Returns: Maschinenname """ try: return socket.gethostname() except: return "Unknown-PC" def get_system_info(self) -> dict: """ Sammelt detaillierte System-Informationen. Returns: Dictionary mit System-Infos """ return { "hostname": self.get_machine_name(), "platform": platform.system(), "platform_release": platform.release(), "platform_version": platform.version(), "architecture": platform.machine(), "processor": self.get_cpu_info(), "python_version": platform.python_version(), "mac_address": self.get_mac_address(), "system_uuid": self.get_system_uuid() } # Test-Funktion if __name__ == "__main__": logging.basicConfig( level=logging.DEBUG, format='%(asctime)s - %(name)s - %(levelname)s - %(message)s' ) print("=== Hardware Fingerprint Test ===\n") fingerprint = HardwareFingerprint() # System-Info anzeigen print("System-Informationen:") info = fingerprint.get_system_info() for key, value in info.items(): print(f" {key}: {value}") # Fingerprint generieren print("\nHardware-Fingerprint:") hw_hash = fingerprint.get_or_create_fingerprint() print(f" Hash: {hw_hash}") print(f" L�nge: {len(hw_hash)} Zeichen") # Maschinenname print(f"\nMaschinenname: {fingerprint.get_machine_name()}") print("\n=== Test abgeschlossen ===")