Dieser Commit ist enthalten in:
Claude Project Manager
2025-07-03 21:11:05 +02:00
Commit 08ed938105
239 geänderte Dateien mit 21554 neuen und 0 gelöschten Zeilen

0
licensing/__init__.py Normale Datei
Datei anzeigen

Binäre Datei nicht angezeigt.

Binäre Datei nicht angezeigt.

Binäre Datei nicht angezeigt.

Binäre Datei nicht angezeigt.

Datei anzeigen

450
licensing/license_manager.py Normale Datei
Datei anzeigen

@ -0,0 +1,450 @@
"""
Lizenzverwaltungsfunktionalität für den Social Media Account Generator.
"""
import os
import json
import time
import uuid
import hmac
import hashlib
import logging
import requests
from datetime import datetime, timedelta
from typing import Dict, List, Any, Optional, Tuple, Union
logger = logging.getLogger("license_manager")
class LicenseManager:
"""Klasse zur Verwaltung von Softwarelizenzen."""
CONFIG_FILE = os.path.join("config", "license.json")
LICENSE_SERVER_URL = "https://api.example.com/license" # Platzhalter - in der Produktion anpassen
def __init__(self):
"""Initialisiert den LicenseManager und lädt die Konfiguration."""
self.license_data = self.load_license_data()
self.machine_id = self.get_machine_id()
# Stelle sicher, dass das Konfigurationsverzeichnis existiert
os.makedirs(os.path.dirname(self.CONFIG_FILE), exist_ok=True)
# Prüfe die Lizenz beim Start
self.verify_license()
def load_license_data(self) -> Dict[str, Any]:
"""Lädt die Lizenzdaten aus der Konfigurationsdatei."""
if not os.path.exists(self.CONFIG_FILE):
return {
"key": "",
"activation_date": "",
"expiry_date": "",
"status": "inactive",
"status_text": "Keine Lizenz aktiviert",
"features": [],
"last_online_check": "",
"signature": ""
}
try:
with open(self.CONFIG_FILE, "r", encoding="utf-8") as f:
license_data = json.load(f)
logger.info(f"Lizenzdaten geladen: Status '{license_data.get('status', 'unbekannt')}'")
return license_data
except Exception as e:
logger.error(f"Fehler beim Laden der Lizenzdaten: {e}")
return {
"key": "",
"activation_date": "",
"expiry_date": "",
"status": "inactive",
"status_text": "Fehler beim Laden der Lizenz",
"features": [],
"last_online_check": "",
"signature": ""
}
def save_license_data(self) -> bool:
"""Speichert die Lizenzdaten in die Konfigurationsdatei."""
try:
with open(self.CONFIG_FILE, "w", encoding="utf-8") as f:
json.dump(self.license_data, f, indent=2)
logger.info("Lizenzdaten gespeichert")
return True
except Exception as e:
logger.error(f"Fehler beim Speichern der Lizenzdaten: {e}")
return False
def get_license_info(self) -> Dict[str, Any]:
"""Gibt die aktuellen Lizenzdaten zurück."""
return self.license_data
def get_machine_id(self) -> str:
"""
Generiert eine eindeutige Maschinen-ID.
Returns:
Eindeutige Maschinen-ID
"""
try:
# Versuche, eine eindeutige Hardware-ID zu generieren
# In der Produktion sollte dies mit einer robusteren Methode ersetzt werden
machine_id_file = os.path.join("config", ".machine_id")
if os.path.exists(machine_id_file):
# Bestehende ID laden
with open(machine_id_file, "r") as f:
return f.read().strip()
else:
# Neue ID generieren
machine_id = str(uuid.uuid4())
with open(machine_id_file, "w") as f:
f.write(machine_id)
return machine_id
except Exception as e:
logger.error(f"Fehler bei der Generierung der Maschinen-ID: {e}")
# Fallback: UUID auf Basis der aktuellen Zeit
return str(uuid.uuid5(uuid.NAMESPACE_DNS, f"fallback-{time.time()}"))
def is_licensed(self) -> bool:
"""
Überprüft, ob eine gültige Lizenz vorhanden ist.
Returns:
True, wenn eine gültige Lizenz vorhanden ist, sonst False
"""
# Prüfe den Status der Lizenz
if self.license_data["status"] not in ["active", "trial"]:
return False
# Prüfe, ob die Lizenz abgelaufen ist
if self.license_data["expiry_date"]:
try:
expiry_date = datetime.fromisoformat(self.license_data["expiry_date"])
if datetime.now() > expiry_date:
logger.warning("Lizenz ist abgelaufen")
self.license_data["status"] = "expired"
self.license_data["status_text"] = "Lizenz abgelaufen"
self.save_license_data()
return False
except Exception as e:
logger.error(f"Fehler beim Parsen des Ablaufdatums: {e}")
return False
# Prüfe, ob regelmäßige Online-Verifizierung erforderlich ist
if self.license_data["last_online_check"]:
try:
last_check = datetime.fromisoformat(self.license_data["last_online_check"])
max_offline_days = 7 # Maximale Tage ohne Online-Check
if datetime.now() > last_check + timedelta(days=max_offline_days):
logger.warning(f"Letzte Online-Überprüfung ist mehr als {max_offline_days} Tage her")
# Versuche, eine Online-Überprüfung durchzuführen
if not self.online_verification():
self.license_data["status"] = "verification_required"
self.license_data["status_text"] = "Online-Überprüfung erforderlich"
self.save_license_data()
return False
except Exception as e:
logger.error(f"Fehler bei der Überprüfung der Online-Verifizierung: {e}")
# Prüfe die Signatur (in der Produktion sollte dies erweitert werden)
if not self.verify_signature():
logger.warning("Ungültige Lizenzsignatur")
self.license_data["status"] = "invalid"
self.license_data["status_text"] = "Ungültige Lizenz (manipuliert)"
self.save_license_data()
return False
return True
def verify_license(self) -> bool:
"""
Überprüft die aktuelle Lizenz.
Returns:
True, wenn die Lizenz gültig ist, sonst False
"""
# Lizenzschlüssel vorhanden?
if not self.license_data["key"]:
logger.info("Kein Lizenzschlüssel vorhanden")
self.license_data["status"] = "inactive"
self.license_data["status_text"] = "Keine Lizenz aktiviert"
self.save_license_data()
return False
return self.is_licensed()
def create_signature(self, data: str) -> str:
"""
Erstellt eine Signatur für die angegebenen Daten.
Args:
data: Zu signierende Daten
Returns:
Signatur als Hexadezimalstring
"""
# In der Produktion sollte ein sicherer Schlüssel verwendet werden
secret_key = "development_secret_key"
# HMAC-SHA256-Signatur erstellen
signature = hmac.new(
secret_key.encode(),
data.encode(),
hashlib.sha256
).hexdigest()
return signature
def verify_signature(self) -> bool:
"""
Überprüft die Signatur der Lizenzdaten.
Returns:
True, wenn die Signatur gültig ist, sonst False
"""
if not self.license_data["signature"]:
return False
# Daten für die Signaturprüfung vorbereiten
data_to_verify = f"{self.license_data['key']}|{self.machine_id}|{self.license_data['activation_date']}|{self.license_data['expiry_date']}"
# Signatur erstellen
computed_signature = self.create_signature(data_to_verify)
# Signatur vergleichen
return computed_signature == self.license_data["signature"]
def online_verification(self) -> bool:
"""
Führt eine Online-Überprüfung der Lizenz durch.
Returns:
True, wenn die Überprüfung erfolgreich war, sonst False
"""
if not self.license_data["key"]:
return False
try:
# Daten für die Lizenzüberprüfung
verification_data = {
"license_key": self.license_data["key"],
"machine_id": self.machine_id,
"product_version": "1.0.0", # In der Produktion aus einer Konfiguration laden
"timestamp": time.time()
}
# Anfrage an den Lizenzserver senden
response = requests.post(
self.LICENSE_SERVER_URL + "/verify",
json=verification_data,
timeout=10
)
if response.status_code == 200:
result = response.json()
if result.get("status") == "active":
# Lizenz ist gültig
logger.info("Online-Lizenzüberprüfung erfolgreich")
# Aktualisiere das Datum der letzten Überprüfung
self.license_data["last_online_check"] = datetime.now().isoformat()
self.save_license_data()
return True
else:
# Lizenz ist ungültig
logger.warning(f"Lizenz ungültig: {result.get('message', 'Unbekannter Fehler')}")
self.license_data["status"] = result.get("status", "invalid")
self.license_data["status_text"] = result.get("message", "Lizenz ungültig")
self.save_license_data()
return False
else:
logger.warning(f"Fehler bei der Online-Überprüfung: HTTP {response.status_code}")
return False
except requests.RequestException as e:
logger.error(f"Netzwerkfehler bei der Online-Überprüfung: {e}")
# Bei Verbindungsproblemen sollte die lokale Lizenz weiterhin gültig bleiben
# In der Produktion kann hier eine Begrenzung der Offline-Zeit implementiert werden
return True
except Exception as e:
logger.error(f"Unerwarteter Fehler bei der Online-Überprüfung: {e}")
return False
def activate_license(self, license_key: str) -> Tuple[bool, str]:
"""
Aktiviert eine Lizenz mit dem angegebenen Schlüssel.
Args:
license_key: Zu aktivierender Lizenzschlüssel
Returns:
(Erfolg, Nachricht)
"""
if not license_key:
return False, "Bitte geben Sie einen Lizenzschlüssel ein."
try:
# In der Produktionsumgebung sollte hier eine Online-Aktivierung erfolgen
# Für Entwicklungszwecke implementieren wir eine einfache lokale Aktivierung
# Simulierte Online-Aktivierung
activation_data = {
"license_key": license_key,
"machine_id": self.machine_id,
"product_version": "1.0.0",
"timestamp": time.time()
}
# Nur für Entwicklung: Prüfe, ob der Lizenzschlüssel bekannt ist
if license_key.startswith("DEV-"):
# Entwicklungslizenzen haben unbegrenzte Laufzeit
expiry_date = (datetime.now() + timedelta(days=365)).isoformat()
activation_response = {
"status": "active",
"message": "Entwicklungslizenz aktiviert",
"activation_date": datetime.now().isoformat(),
"expiry_date": expiry_date,
"features": ["all"]
}
elif license_key.startswith("TRIAL-"):
# Trial-Lizenzen haben begrenzte Laufzeit
expiry_date = (datetime.now() + timedelta(days=30)).isoformat()
activation_response = {
"status": "trial",
"message": "Trial-Lizenz aktiviert (30 Tage)",
"activation_date": datetime.now().isoformat(),
"expiry_date": expiry_date,
"features": ["basic"]
}
else:
# Alle anderen Schlüssel simulieren eine Online-Aktivierung
try:
# Anfrage an den Lizenzserver senden
response = requests.post(
self.LICENSE_SERVER_URL + "/activate",
json=activation_data,
timeout=10
)
if response.status_code == 200:
activation_response = response.json()
else:
logger.warning(f"Fehler bei der Lizenzaktivierung: HTTP {response.status_code}")
return False, f"Fehler bei der Lizenzaktivierung: HTTP {response.status_code}"
except requests.RequestException as e:
logger.error(f"Netzwerkfehler bei der Lizenzaktivierung: {e}")
return False, f"Netzwerkfehler bei der Lizenzaktivierung: {e}"
except Exception as e:
logger.error(f"Unerwarteter Fehler bei der Lizenzaktivierung: {e}")
return False, f"Unerwarteter Fehler bei der Lizenzaktivierung: {e}"
# Lizenzdaten aktualisieren
self.license_data["key"] = license_key
self.license_data["status"] = activation_response.get("status", "inactive")
self.license_data["status_text"] = activation_response.get("message", "Unbekannter Status")
self.license_data["activation_date"] = activation_response.get("activation_date", datetime.now().isoformat())
self.license_data["expiry_date"] = activation_response.get("expiry_date", "")
self.license_data["features"] = activation_response.get("features", [])
self.license_data["last_online_check"] = datetime.now().isoformat()
# Signatur erstellen
data_to_sign = f"{self.license_data['key']}|{self.machine_id}|{self.license_data['activation_date']}|{self.license_data['expiry_date']}"
self.license_data["signature"] = self.create_signature(data_to_sign)
# Lizenzdaten speichern
self.save_license_data()
logger.info(f"Lizenz '{license_key}' erfolgreich aktiviert: {self.license_data['status_text']}")
return True, self.license_data["status_text"]
except Exception as e:
error_msg = f"Fehler bei der Lizenzaktivierung: {e}"
logger.error(error_msg)
return False, error_msg
def deactivate_license(self) -> Tuple[bool, str]:
"""
Deaktiviert die aktuelle Lizenz.
Returns:
(Erfolg, Nachricht)
"""
if not self.license_data["key"]:
return False, "Keine Lizenz aktiviert"
old_key = self.license_data["key"]
try:
# Online-Deaktivierung simulieren
deactivation_data = {
"license_key": self.license_data["key"],
"machine_id": self.machine_id,
"timestamp": time.time()
}
# Anfrage für die Produktionsumgebung
# response = requests.post(
# self.LICENSE_SERVER_URL + "/deactivate",
# json=deactivation_data,
# timeout=10
# )
# Lizenzdaten zurücksetzen
self.license_data = {
"key": "",
"activation_date": "",
"expiry_date": "",
"status": "inactive",
"status_text": "Keine Lizenz aktiviert",
"features": [],
"last_online_check": "",
"signature": ""
}
# Lizenzdaten speichern
self.save_license_data()
logger.info(f"Lizenz '{old_key}' erfolgreich deaktiviert")
return True, "Lizenz erfolgreich deaktiviert"
except Exception as e:
error_msg = f"Fehler bei der Lizenzdeaktivierung: {e}"
logger.error(error_msg)
return False, error_msg
def has_feature(self, feature_name: str) -> bool:
"""
Überprüft, ob die aktuelle Lizenz eine bestimmte Funktion unterstützt.
Args:
feature_name: Name der zu überprüfenden Funktion
Returns:
True, wenn die Funktion unterstützt wird, sonst False
"""
if not self.is_licensed():
return False
# "all" bedeutet, dass alle Funktionen unterstützt werden
if "all" in self.license_data["features"]:
return True
return feature_name in self.license_data["features"]

304
licensing/license_validator.py Normale Datei
Datei anzeigen

@ -0,0 +1,304 @@
"""
Lizenzvalidator - Validiert Lizenzschlüssel und enthält Sicherheitsalgorithmen
"""
import os
import logging
import hashlib
import hmac
import base64
import json
import time
import random
import string
from datetime import datetime, timedelta
from typing import Dict, Optional, Tuple, Any, List
# Konfiguriere Logger
logger = logging.getLogger("license_validator")
class LicenseValidator:
"""
Validiert Lizenzschlüssel und führt kryptografische Operationen durch.
Enthält Platzhaltercode für die Lizenzvalidierung.
"""
# Sicherheitsschlüssel (würde in einer echten Implementierung nicht im Code stehen)
SECRET_KEY = "5e884898da28047151d0e56f8dc6292773603d0d6aabbdd62a11ef721d1542d8"
def __init__(self):
"""Initialisiert den LicenseValidator."""
logger.info("Lizenzvalidator initialisiert")
def validate_key_format(self, license_key: str) -> bool:
"""
Prüft, ob der Lizenzschlüssel das richtige Format hat.
Args:
license_key: Der zu prüfende Lizenzschlüssel
Returns:
bool: True, wenn das Format gültig ist, False sonst
"""
# Einfacher Formatcheck für XXXXX-XXXXX-XXXXX-XXXXX
import re
return bool(re.match(r'^[A-Z0-9]{5}-[A-Z0-9]{5}-[A-Z0-9]{5}-[A-Z0-9]{5}$', license_key))
def validate_key_checksum(self, license_key: str) -> bool:
"""
Prüft, ob die Prüfsumme des Lizenzschlüssels gültig ist.
Args:
license_key: Der zu prüfende Lizenzschlüssel
Returns:
bool: True, wenn die Prüfsumme gültig ist, False sonst
"""
# Platzhalterimplementierung - in einer echten Implementierung würde hier
# eine Prüfsummenberechnung stehen
# Entferne Bindestriche für die Verarbeitung
key_parts = license_key.split('-')
if len(key_parts) != 4:
return False
# Einfacher Check: Letzter Buchstabe des ersten Teils ist abhängig von den ersten Buchstaben
# der anderen Teile (XOR der ASCII-Werte)
try:
check_char = key_parts[0][-1]
calculated_char = chr(ord(key_parts[1][0]) ^ ord(key_parts[2][0]) ^ ord(key_parts[3][0]))
# In einer echten Implementierung wäre diese Prüfung viel stärker
return check_char == calculated_char
except IndexError:
return False
except Exception as e:
logger.error(f"Fehler bei der Prüfsummenberechnung: {e}")
return False
def decrypt_license_data(self, license_key: str) -> Optional[Dict[str, Any]]:
"""
Entschlüsselt Lizenzinformationen aus dem Schlüssel.
Args:
license_key: Der zu entschlüsselnde Lizenzschlüssel
Returns:
Optional[Dict[str, Any]]: Entschlüsselte Lizenzdaten oder None bei Fehler
"""
# Platzhalterimplementierung - in einer echten Implementierung würde hier
# eine Entschlüsselung stehen
if not self.validate_key_format(license_key):
return None
# Mock-Daten generieren
key_parts = license_key.split('-')
# Aus dem Schlüssel Informationen "ableiten"
try:
# Verwende den ersten Teil für die Lizenzart
license_type_index = sum(ord(c) for c in key_parts[0]) % 3
license_types = ["basic", "premium", "enterprise"]
license_type = license_types[license_type_index]
# Verwende den zweiten Teil für die Gültigkeitsdauer
validity_months = (sum(ord(c) for c in key_parts[1]) % 12) + 1
# Verwende den dritten Teil für die Funktionen
features_count = (sum(ord(c) for c in key_parts[2]) % 5) + 1
all_features = ["multi_account", "proxy_rotation", "advanced_analytics",
"sms_verification", "captcha_solving", "phone_verification",
"export", "scheduling"]
features = all_features[:features_count]
# Generiere ein "verschlüsseltes" Token
token = hashlib.sha256(license_key.encode()).hexdigest()
# Aktuelle Zeit für Aktivierung
now = datetime.now()
activation_date = now.strftime("%Y-%m-%d %H:%M:%S")
expiry_date = (now + timedelta(days=30*validity_months)).strftime("%Y-%m-%d %H:%M:%S")
# Lizenzdaten zusammenstellen
license_data = {
"license_type": license_type,
"features": features,
"activation_date": activation_date,
"expiry_date": expiry_date,
"token": token
}
return license_data
except Exception as e:
logger.error(f"Fehler bei der Entschlüsselung des Lizenzschlüssels: {e}")
return None
def generate_license_key(self, license_type: str = "basic", validity_months: int = 12,
features: List[str] = None) -> str:
"""
Generiert einen Lizenzschlüssel.
Args:
license_type: Art der Lizenz ("basic", "premium", "enterprise")
validity_months: Gültigkeitsdauer in Monaten
features: Liste der Funktionen
Returns:
str: Generierter Lizenzschlüssel
"""
# Platzhalterimplementierung - in einer echten Implementierung würde hier
# eine sichere Schlüsselgenerierung stehen
# Verwende die Eingabeparameter als Seed für die Generierung
seed = f"{license_type}{validity_months}{','.join(features or [])}{time.time()}"
random.seed(hashlib.md5(seed.encode()).hexdigest())
# Generiere 4 Teile mit jeweils 5 Zeichen (Großbuchstaben und Zahlen)
chars = string.ascii_uppercase + string.digits
parts = []
for _ in range(4):
part = ''.join(random.choice(chars) for _ in range(5))
parts.append(part)
# Stelle sicher, dass der letzte Buchstabe des ersten Teils
# ein XOR der ersten Buchstaben der anderen Teile ist
# (für die einfache Prüfsumme)
calc_char = chr(ord(parts[1][0]) ^ ord(parts[2][0]) ^ ord(parts[3][0]))
parts[0] = parts[0][:-1] + calc_char
# Verbinde die Teile mit Bindestrichen
license_key = '-'.join(parts)
return license_key
def sign_data(self, data: str) -> str:
"""
Signiert Daten mit dem geheimen Schlüssel.
Args:
data: Zu signierende Daten
Returns:
str: Signatur
"""
return hmac.new(
self.SECRET_KEY.encode(),
data.encode(),
hashlib.sha256
).hexdigest()
def verify_signature(self, data: str, signature: str) -> bool:
"""
Überprüft die Signatur von Daten.
Args:
data: Signierte Daten
signature: Zu überprüfende Signatur
Returns:
bool: True, wenn die Signatur gültig ist, False sonst
"""
expected_signature = self.sign_data(data)
return hmac.compare_digest(expected_signature, signature)
def encode_license_data(self, data: Dict[str, Any]) -> str:
"""
Kodiert Lizenzdaten zur sicheren Übertragung.
Args:
data: Zu kodierende Lizenzdaten
Returns:
str: Kodierte Lizenzdaten
"""
# Daten in JSON konvertieren
json_data = json.dumps(data, sort_keys=True)
# Signatur hinzufügen
signature = self.sign_data(json_data)
# Zusammen mit der Signatur kodieren
combined = f"{json_data}|{signature}"
encoded = base64.b64encode(combined.encode()).decode()
return encoded
def decode_license_data(self, encoded: str) -> Optional[Dict[str, Any]]:
"""
Dekodiert und überprüft kodierte Lizenzdaten.
Args:
encoded: Kodierte Lizenzdaten
Returns:
Optional[Dict[str, Any]]: Dekodierte Lizenzdaten oder None bei Fehler
"""
try:
# Dekodieren
decoded = base64.b64decode(encoded).decode()
# In Daten und Signatur aufteilen
json_data, signature = decoded.split('|', 1)
# Signatur überprüfen
if not self.verify_signature(json_data, signature):
logger.warning("Ungültige Signatur in lizenzierten Daten")
return None
# JSON parsen
data = json.loads(json_data)
return data
except Exception as e:
logger.error(f"Fehler beim Dekodieren der Lizenzdaten: {e}")
return None
# Beispielnutzung, wenn direkt ausgeführt
if __name__ == "__main__":
# Konfiguriere Logging
logging.basicConfig(
level=logging.INFO,
format='%(asctime)s - %(name)s - %(levelname)s - %(message)s'
)
# Beispiel für LicenseValidator
validator = LicenseValidator()
# Generiere einen Lizenzschlüssel
features = ["multi_account", "proxy_rotation", "advanced_analytics"]
key = validator.generate_license_key("premium", 12, features)
print(f"Generierter Lizenzschlüssel: {key}")
# Validiere den Schlüssel
is_valid_format = validator.validate_key_format(key)
is_valid_checksum = validator.validate_key_checksum(key)
print(f"Format gültig: {is_valid_format}")
print(f"Prüfsumme gültig: {is_valid_checksum}")
# Entschlüssele Lizenzdaten
license_data = validator.decrypt_license_data(key)
if license_data:
print("\nEntschlüsselte Lizenzdaten:")
for k, v in license_data.items():
print(f" {k}: {v}")
# Beispiel für Kodierung und Dekodierung
test_data = {
"name": "Test License",
"type": "premium",
"expires": "2026-01-01"
}
encoded = validator.encode_license_data(test_data)
print(f"\nKodierte Daten: {encoded}")
decoded = validator.decode_license_data(encoded)
if decoded:
print("\nDekodierte Daten:")
for k, v in decoded.items():
print(f" {k}: {v}")