# 🛡️ Protection Licence Anti-Contournement

*Sécurisation avancée contre le reverse engineering et la modification de licence*

---

## 🎯 **Problématique**

**Défi** : Empêcher qu'un utilisateur puisse :
- ✋ Modifier la date système pour prolonger la licence
- 🔓 Cracker le fichier de licence chiffré
- 🔄 Contourner les vérifications d'expiration
- 📝 Modifier le code pour bypasser les contrôles

**Objectif** : Système de protection multicouche avec validation serveur intelligente

---

## 🏗️ **Architecture Hybride Recommandée**

### **Principe : "Zero Trust Local + Validation Serveur Légère"**

```mermaid
flowchart TD
    A[Application démarrage] --> B[Lecture licence locale]
    B --> C[Validation cryptographique]
    C --> D{Licence structurellement valide?}
    D -->|❌| E[ARRÊT - Licence corrompue]
    D -->|✅| F[Validation anti-tampering]
    F --> G[Vérification serveur périodique]
    G --> H{Serveur accessible?}
    H -->|❌| I[Mode dégradé avec grace period]
    H -->|✅| J[Validation authoritative]
    J --> K{Licence serveur OK?}
    K -->|❌| L[ARRÊT - Licence révoquée]
    K -->|✅| M[Application fonctionnelle]
    I --> N[Compteur offline limité]
    N --> O{Grace period dépassée?}
    O -->|✅| P[ARRÊT - Reconnexion requise]
    O -->|❌| M
```

---

## 🔐 **Couches de Protection**

### **Niveau 1 : Protection Cryptographique Locale**

#### **A. Licence multi-signatures**
```json
{
  "license": {
    "id": "WS-ENT-2024-ABC123",
    "customer": "ACME Corp",
    "tier": "ENTERPRISE",
    "validUntil": "2025-12-31T23:59:59Z",
    "issuedAt": "2024-10-14T10:00:00Z",
    "features": ["invasive_tests", "api_access"]
  },
  "signatures": {
    "primary": "RSA4096_signature_base64",
    "timestamp": "RFC3161_timestamp_signature",
    "integrity": "HMAC_SHA256_content_hash"
  },
  "antiTampering": {
    "systemFingerprint": "hw_cpu_motherboard_hash",
    "appChecksum": "SHA256_executable_hash",
    "installationId": "unique_installation_uuid"
  }
}
```

#### **B. Horodatage cryptographique**
```python
# Protection contre modification date système
import time
from cryptography.hazmat.primitives import hashes
from cryptography.hazmat.primitives.asymmetric import rsa

class TimestampValidator:
    def __init__(self):
        self.tsa_public_key = self._load_tsa_public_key()
        
    def validate_timestamp(self, license_data: dict) -> bool:
        """Valide l'horodatage RFC3161 de la licence"""
        timestamp_token = license_data["signatures"]["timestamp"]
        
        # Vérification signature TSA (Time Stamping Authority)
        return self._verify_tsa_signature(timestamp_token)
        
    def check_system_time_manipulation(self) -> bool:
        """Détecte les modifications suspectes de l'heure système"""
        ntp_time = self._get_ntp_time()
        system_time = time.time()
        
        # Tolérance de 5 minutes maximum
        return abs(ntp_time - system_time) < 300
```

### **Niveau 2 : Validation Serveur Intelligente**

#### **A. Base de données licence authoritative**
```sql
-- Table côté serveur (votre infrastructure)
CREATE TABLE license_registry (
    license_id VARCHAR(50) PRIMARY KEY,
    customer_email VARCHAR(255) NOT NULL,
    tier ENUM('PRO', 'ENTERPRISE', 'CORPORATE'),
    issued_date TIMESTAMP NOT NULL,
    expiry_date TIMESTAMP NOT NULL,
    status ENUM('ACTIVE', 'SUSPENDED', 'REVOKED', 'EXPIRED'),
    last_validation TIMESTAMP,
    validation_count INT DEFAULT 0,
    max_offline_days INT DEFAULT 7,
    hardware_fingerprint VARCHAR(255),
    installation_count INT DEFAULT 0,
    max_installations INT DEFAULT 1,
    created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
    updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP
);

-- Historique des validations
CREATE TABLE validation_history (
    id BIGINT AUTO_INCREMENT PRIMARY KEY,
    license_id VARCHAR(50),
    client_ip VARCHAR(45),
    user_agent TEXT,
    validation_timestamp TIMESTAMP,
    system_time_client TIMESTAMP,
    hardware_fingerprint VARCHAR(255),
    app_version VARCHAR(20),
    validation_result ENUM('SUCCESS', 'EXPIRED', 'REVOKED', 'INVALID'),
    FOREIGN KEY (license_id) REFERENCES license_registry(license_id)
);
```

#### **B. API de validation sécurisée**
```python
# Côté serveur (votre API)
from flask import Flask, request, jsonify
from cryptography.fernet import Fernet
import hmac
import hashlib

class LicenseValidationAPI:
    def __init__(self):
        self.encryption_key = Fernet.generate_key()
        self.hmac_secret = "your_secret_key_here"
    
    def validate_license(self, license_id: str, client_data: dict) -> dict:
        """Validation authoritative côté serveur"""
        
        # 1. Vérification HMAC pour éviter tampering
        if not self._verify_request_integrity(client_data):
            return {"status": "INVALID", "reason": "Request tampering detected"}
        
        # 2. Lookup base de données
        license_record = self._get_license_from_db(license_id)
        if not license_record:
            return {"status": "INVALID", "reason": "License not found"}
        
        # 3. Vérifications multiples
        checks = [
            self._check_expiry(license_record),
            self._check_status(license_record),
            self._check_hardware_binding(license_record, client_data),
            self._check_installation_limit(license_record, client_data),
            self._check_suspicious_activity(license_record, client_data)
        ]
        
        if not all(checks):
            return {"status": "INVALID", "reason": "Validation failed"}
        
        # 4. Mise à jour dernière validation
        self._update_last_validation(license_id, client_data)
        
        # 5. Calcul grace period offline
        grace_period_hours = self._calculate_grace_period(license_record)
        
        return {
            "status": "VALID",
            "expires_at": license_record["expiry_date"],
            "grace_period_hours": grace_period_hours,
            "next_validation_required": self._next_validation_date(),
            "features": license_record["features"]
        }
```

### **Niveau 3 : Protection Applicative**

#### **A. Vérifications distribuées dans le code**
```python
# Protection contre patching
import random
import threading

class DistributedLicenseChecker:
    def __init__(self, license_manager):
        self.license_manager = license_manager
        self.checks_performed = 0
        self.last_server_validation = None
        
    def random_license_check(self):
        """Vérification aléatoire pendant l'exécution"""
        if random.randint(1, 100) <= 5:  # 5% de chance
            if not self._validate_license_state():
                self._emergency_shutdown()
    
    def periodic_validation_thread(self):
        """Thread de validation périodique"""
        while True:
            time.sleep(random.randint(3600, 7200))  # 1-2h aléatoire
            
            try:
                result = self._contact_validation_server()
                if result["status"] != "VALID":
                    self._initiate_grace_period()
            except:
                self._handle_offline_mode()
    
    def feature_usage_validation(self, feature_name: str):
        """Validation à chaque utilisation de feature premium"""
        if not self.license_manager.has_feature(feature_name):
            raise LicenseViolationError(f"Feature {feature_name} not licensed")
            
        # Validation serveur périodique
        if self._should_validate_with_server():
            self._async_server_validation()
```

#### **B. Mode offline avec grace period**
```python
class OfflineGraceManager:
    def __init__(self, max_offline_days=7):
        self.max_offline_days = max_offline_days
        self.offline_start = None
        
    def enter_offline_mode(self):
        """Mode dégradé sans connexion serveur"""
        self.offline_start = datetime.utcnow()
        
        # Stockage chiffré local de l'état offline
        offline_state = {
            "offline_since": self.offline_start,
            "validation_attempts": 0,
            "last_valid_response": self._get_last_server_response()
        }
        
        self._store_encrypted_offline_state(offline_state)
    
    def check_grace_period(self) -> bool:
        """Vérifie si la grace period est encore valide"""
        if not self.offline_start:
            return True
            
        offline_duration = datetime.utcnow() - self.offline_start
        return offline_duration.days < self.max_offline_days
    
    def get_grace_period_warning(self) -> str:
        """Message d'avertissement utilisateur"""
        if not self.offline_start:
            return ""
            
        days_offline = (datetime.utcnow() - self.offline_start).days
        days_remaining = self.max_offline_days - days_offline
        
        if days_remaining <= 1:
            return f"⚠️ URGENT: Connexion internet requise dans {days_remaining} jour(s)"
        else:
            return f"🔄 Mode offline: {days_remaining} jours restants"
```

---

## 🚨 **Détection Anti-Tampering**

### **Hardware Fingerprinting**
```python
import platform
import subprocess
import hashlib

class HardwareFingerprinter:
    def generate_fingerprint(self) -> str:
        """Génère une empreinte matérielle unique"""
        components = [
            self._get_cpu_id(),
            self._get_motherboard_serial(),
            self._get_mac_addresses(),
            self._get_disk_serial(),
            platform.machine(),
            platform.processor()
        ]
        
        # Hash stable des composants
        fingerprint_data = "|".join(filter(None, components))
        return hashlib.sha256(fingerprint_data.encode()).hexdigest()
    
    def _get_cpu_id(self) -> str:
        """ID processeur unique"""
        try:
            if platform.system() == "Windows":
                result = subprocess.run(
                    ["wmic", "cpu", "get", "ProcessorId", "/value"],
                    capture_output=True, text=True
                )
                return result.stdout.split("=")[1].strip()
        except:
            return ""
    
    def validate_hardware_binding(self, stored_fingerprint: str) -> bool:
        """Validation que l'app tourne sur le bon hardware"""
        current_fp = self.generate_fingerprint()
        
        # Tolérance pour changements mineurs (80% similarité)
        similarity = self._calculate_similarity(current_fp, stored_fingerprint)
        return similarity >= 0.8
```

### **Application Integrity Checks**
```python
class ApplicationIntegrityChecker:
    def __init__(self, expected_checksums: dict):
        self.expected_checksums = expected_checksums
        
    def verify_executable_integrity(self) -> bool:
        """Vérifie que l'executable n'a pas été modifié"""
        current_exe_path = sys.executable
        current_checksum = self._calculate_file_hash(current_exe_path)
        
        return current_checksum in self.expected_checksums.values()
    
    def verify_critical_modules(self) -> bool:
        """Vérifie l'intégrité des modules critiques"""
        critical_modules = [
            "web_sentinel.license.license_manager",
            "web_sentinel.license.crypto_utils",
            "web_sentinel.license.validation"
        ]
        
        for module_name in critical_modules:
            if not self._verify_module_integrity(module_name):
                return False
        return True
    
    def detect_debugger_attachment(self) -> bool:
        """Détecte si un debugger est attaché"""
        import ctypes
        
        if platform.system() == "Windows":
            kernel32 = ctypes.windll.kernel32
            return kernel32.IsDebuggerPresent()
        return False
```

---

## 🔄 **Stratégies de Validation**

### **1. Validation Fréquente mais Intelligente**
```python
class SmartValidationScheduler:
    def __init__(self):
        self.validation_intervals = {
            "startup": True,                    # Toujours au démarrage
            "daily": True,                      # Une fois par jour
            "feature_usage": 0.05,             # 5% lors utilisation features
            "random_runtime": 0.01,            # 1% pendant exécution
            "network_reconnect": True,         # Après reconnexion réseau
            "suspicious_activity": True        # Si activité suspecte détectée
        }
    
    def should_validate_now(self, trigger: str) -> bool:
        """Décide si une validation est nécessaire"""
        if trigger == "startup":
            return True
        elif trigger == "daily":
            return self._last_validation_older_than(hours=24)
        elif trigger in ["feature_usage", "random_runtime"]:
            return random.random() < self.validation_intervals[trigger]
        else:
            return self.validation_intervals.get(trigger, False)
```

### **2. Système d'alertes graduelles**
```python
class LicenseExpiryAlerts:
    def __init__(self):
        self.alert_thresholds = [30, 14, 7, 3, 1]  # Jours avant expiration
        
    def check_and_show_alerts(self, license_expiry: datetime):
        """Affiche alertes d'expiration graduelles"""
        days_remaining = (license_expiry - datetime.utcnow()).days
        
        for threshold in self.alert_thresholds:
            if days_remaining <= threshold:
                self._show_expiry_warning(days_remaining, threshold)
                break
    
    def _show_expiry_warning(self, days_remaining: int, threshold: int):
        """Affiche l'alerte appropriée"""
        if days_remaining <= 1:
            self._show_urgent_renewal_dialog()
        elif days_remaining <= 7:
            self._show_renewal_reminder()
        else:
            self._show_gentle_reminder()
```

---

## 🛠️ **Implémentation Recommandée**

### **Phase 1 : Infrastructure Serveur (Semaine 1)**
1. **API de validation** : Endpoint sécurisé avec rate limiting
2. **Base de données licence** : Registre authoritative avec historique
3. **Monitoring** : Détection activités suspectes et tentatives de contournement

### **Phase 2 : Protection Client (Semaine 2)**
1. **Hardware fingerprinting** : Liaison matérielle optionnelle
2. **Integrity checks** : Vérification executable et modules critiques
3. **Anti-debugging** : Protection contre reverse engineering

### **Phase 3 : Validation Distribuée (Semaine 3)**
1. **Vérifications multiples** : Checks répartis dans le code
2. **Grace period offline** : Mode dégradé avec limite temporelle
3. **Alertes utilisateur** : Système de notifications graduelles

### **Phase 4 : Monitoring & Analytics (Semaine 4)**
1. **Dashboard admin** : Suivi licences et détection anomalies
2. **Analytics usage** : Métriques d'utilisation par licence
3. **Système d'alertes** : Notifications admin pour activités suspectes

---

## 💡 **Recommandations Finales**

### **✅ Approche Équilibrée :**
- **🔄 Validation serveur légère** : Pas à chaque clic, mais périodique intelligente
- **🏠 Fonctionnement offline** : Grace period de 7 jours maximum
- **🎯 UX préservée** : Validations transparentes pour l'utilisateur
- **🛡️ Protection robuste** : Multi-couches contre contournement

### **⚠️ Points d'Attention :**
- **Réseau requis périodiquement** : Informer clairement les clients
- **Backup validation** : Plan B si serveur indisponible
- **Support technique** : Processus pour débloquer licences légitimes
- **Compliance** : Respect RGPD pour données collectées

Cette approche offre le meilleur compromis entre **sécurité robuste** et **expérience utilisateur acceptable**, tout en protégeant efficacement votre investissement ! 🚀

### **🏛️ Solutions Spécialisées Segments Premium**

**Pour Gouvernement, Finance, Santé** → **[SEGMENTS_PREMIUM_AIRGAP.md](SEGMENTS_PREMIUM_AIRGAP.md)**

Ces environnements critiques nécessitent des solutions adaptées :
- **🚫 Mode Air-Gap** : Validation 100% locale sans internet
- **🔐 Licence Souveraine** : Certificats long terme (1-5 ans)
- **🏛️ Conformité renforcée** : ANSSI, FDA, SOX, HIPAA
- **💰 Pricing premium** : 15k€-200k€ selon segment et classification

---

*🔐 Protection Licence Web Sentinel - Guide Technique v1.0*