import 'dart:io'; import 'package:freerasp/freerasp.dart'; import 'package:flutter/foundation.dart'; import '../config/environment.dart'; import '../utils/logger.dart'; /// Service de détection d'intégrité applicative — MASVS v2 RESILIENCE. /// /// Utilise freeRASP pour détecter : /// - Root/Jailbreak /// - Debugger attaché /// - Émulateur /// - Application hookuée (Frida, Xposed) /// - Signature APK altérée /// - Device binding /// /// En prod [AppConfig.isProd], déclenche la fermeture forcée de l'app /// si une menace critique est détectée. En dev, log uniquement. class AppIntegrityService { static const _tag = 'AppIntegrityService'; static AppIntegrityService? _instance; static AppIntegrityService get instance => _instance ??= AppIntegrityService._(); AppIntegrityService._(); bool _initialized = false; /// Initialise freeRASP et démarre la surveillance en temps réel. /// À appeler depuis [main()] après [WidgetsFlutterBinding.ensureInitialized()]. Future initialize({ required void Function(String threat) onThreatDetected, }) async { if (_initialized) return; // Pas d'init en debug web if (kIsWeb) { AppLogger.info('freeRASP désactivé sur web', tag: _tag); _initialized = true; return; } try { final config = _buildConfig(); final callbacks = ThreatCallback( // Menaces critiques — terminer l'app en prod onPrivilegedAccess: () => _handleThreat('ROOT_DETECTED', onThreatDetected), onDebug: () => _handleThreat('DEBUGGER_DETECTED', onThreatDetected), onAppIntegrity: () => _handleThreat('SIGNATURE_TAMPERED', onThreatDetected), onHooks: () => _handleThreat('HOOK_DETECTED', onThreatDetected), // Menaces modérées — alerter sans bloquer onSimulator: () => _handleThreatModerate('EMULATOR_DETECTED', onThreatDetected), onUnofficialStore: () => _handleThreatModerate('UNTRUSTED_SOURCE', onThreatDetected), onDeviceBinding: () => _handleThreatModerate('DEVICE_BINDING', onThreatDetected), onObfuscationIssues: () => AppLogger.warning('Problème obfuscation détecté', tag: _tag), ); await Talsec.instance.start(config); await Talsec.instance.attachListener(callbacks); _initialized = true; AppLogger.info('freeRASP initialisé avec succès', tag: _tag); } catch (e) { AppLogger.error('Erreur init freeRASP: $e', tag: _tag); _initialized = true; // Ne pas bloquer le démarrage } } TalsecConfig _buildConfig() { final androidConfig = AndroidConfig( packageName: 'dev.lions.unionflow', signingCertHashes: [ // SHA-256 du certificat de signature release (à renseigner avant go-live) // Obtenir avec : keytool -printcert -jarfile app-release.apk | grep SHA256 'PLACEHOLDER_SHA256_RELEASE_CERT_HASH', ], supportedStores: [], ); final iosConfig = IOSConfig( bundleIds: ['dev.lions.unionflow'], teamId: 'PLACEHOLDER_TEAM_ID', ); return TalsecConfig( androidConfig: androidConfig, iosConfig: iosConfig, watcherMail: 'security@lions.dev', isProd: AppConfig.isProd, ); } void _handleThreat( String threat, void Function(String) onThreatDetected) { AppLogger.warning('Menace CRITIQUE détectée: $threat', tag: _tag); onThreatDetected(threat); if (AppConfig.isProd) { AppLogger.warning('Fermeture forcée suite à menace critique: $threat', tag: _tag); exit(0); } } void _handleThreatModerate( String threat, void Function(String) onThreatDetected) { AppLogger.warning('Menace modérée détectée: $threat', tag: _tag); onThreatDetected(threat); // Pas de fermeture forcée pour les menaces modérées } }