/** * SecurityModeService - Gestion des modes de sécurisation * Gère le stockage et la récupération du mode de sécurisation choisi par l'utilisateur */ import { secureLogger } from './secure-logger'; import Database from './database.service'; export type SecurityMode = 'proton-pass' | 'os' | 'browser' | 'otp' | '2fa' | 'password' | 'none'; export interface SecurityModeConfig { mode: SecurityMode; name: string; description: string; securityLevel: 'high' | 'medium' | 'low' | 'critical'; requiresConfirmation: boolean; warnings: string[]; implementation: { useWebAuthn: boolean; useEncryption: boolean; usePlatformAuth: boolean; storageType: 'encrypted' | 'plain' | 'hybrid'; }; } export class SecurityModeService { private static instance: SecurityModeService; private database: Database; private currentMode: SecurityMode | null = null; private constructor() { this.database = new Database(); } public static getInstance(): SecurityModeService { if (!SecurityModeService.instance) { SecurityModeService.instance = new SecurityModeService(); } return SecurityModeService.instance; } /** * Récupère le mode de sécurisation actuel */ public async getCurrentMode(): Promise { if (this.currentMode) { return this.currentMode; } try { // Vérifier que la base de données est disponible if (!this.database || typeof this.database.getObject !== 'function') { secureLogger.warn('Database not available, returning null mode', { component: 'SecurityModeService', operation: 'getCurrentMode' }); return null; } const storedMode = await this.database.getObject('security_settings', 'current_mode'); this.currentMode = storedMode?.mode || null; secureLogger.info('Current security mode retrieved', { component: 'SecurityModeService', operation: 'getCurrentMode', mode: this.currentMode }); return this.currentMode; } catch (error) { // Si l'erreur est "object store not found", c'est normal pour un premier lancement if (error instanceof Error && (error.name === 'NotFoundError' || error.message.includes('object stores was not found'))) { secureLogger.info('No security mode set yet (first launch)', { component: 'SecurityModeService', operation: 'getCurrentMode' }); return null; } secureLogger.error('Failed to retrieve current security mode', error as Error, { component: 'SecurityModeService', operation: 'getCurrentMode' }); return null; } } /** * Définit le mode de sécurisation */ public async setSecurityMode(mode: SecurityMode): Promise { try { const modeConfig = this.getSecurityModeConfig(mode); // Vérifier que la base de données est disponible if (!this.database || typeof this.database.setObject !== 'function') { secureLogger.warn('Database not available, setting mode in memory only', { component: 'SecurityModeService', operation: 'setSecurityMode', mode }); this.currentMode = mode; return; } // Stocker le mode en base await this.database.setObject('security_settings', 'current_mode', { mode, name: modeConfig.name, description: modeConfig.description, securityLevel: modeConfig.securityLevel, timestamp: Date.now(), implementation: modeConfig.implementation }); this.currentMode = mode; secureLogger.info('Security mode set successfully', { component: 'SecurityModeService', operation: 'setSecurityMode', mode, securityLevel: modeConfig.securityLevel }); // Émettre un événement pour notifier les autres services window.dispatchEvent(new CustomEvent('securityModeChanged', { detail: { mode, config: modeConfig } })); } catch (error) { secureLogger.error('Failed to set security mode', error as Error, { component: 'SecurityModeService', operation: 'setSecurityMode', mode }); // En cas d'erreur, définir le mode en mémoire seulement this.currentMode = mode; secureLogger.warn('Security mode set in memory only due to database error', { component: 'SecurityModeService', operation: 'setSecurityMode', mode }); } } /** * Récupère la configuration d'un mode de sécurisation */ public getSecurityModeConfig(mode: SecurityMode): SecurityModeConfig { const configs: Record = { 'proton-pass': { mode: 'proton-pass', name: 'Proton Pass', description: 'Utilise Proton Pass pour l\'authentification biométrique et la gestion des clés', securityLevel: 'high', requiresConfirmation: false, warnings: [], implementation: { useWebAuthn: true, useEncryption: true, usePlatformAuth: true, storageType: 'encrypted' } }, 'os': { mode: 'os', name: 'Authentificateur OS', description: 'Utilise l\'authentificateur intégré de votre système d\'exploitation', securityLevel: 'high', requiresConfirmation: false, warnings: [], implementation: { useWebAuthn: true, useEncryption: true, usePlatformAuth: true, storageType: 'encrypted' } }, 'browser': { mode: 'browser', name: 'Navigateur', description: 'Utilise les fonctionnalités de sécurité du navigateur', securityLevel: 'medium', requiresConfirmation: false, warnings: [], implementation: { useWebAuthn: true, useEncryption: true, usePlatformAuth: false, storageType: 'encrypted' } }, 'otp': { mode: 'otp', name: 'OTP (Proton Pass Compatible)', description: 'Utilise un code OTP généré par une application compatible (Proton Pass, Google Authenticator, etc.)', securityLevel: 'high', requiresConfirmation: false, warnings: [], implementation: { useWebAuthn: false, useEncryption: true, usePlatformAuth: false, storageType: 'encrypted', requiresOTP: true } }, '2fa': { mode: '2fa', name: 'Application 2FA', description: 'Stockage en clair avec authentification par application 2FA', securityLevel: 'low', requiresConfirmation: true, warnings: [ '⚠️ Clés stockées en clair', '⚠️ Risque de compromission', '⚠️ Non recommandé pour des données sensibles' ], implementation: { useWebAuthn: false, useEncryption: false, usePlatformAuth: false, storageType: 'plain' } }, 'password': { mode: 'password', name: 'Mot de Passe (Non Sauvegardé)', description: 'Vos clés sont chiffrées avec un mot de passe que vous devez saisir à chaque utilisation', securityLevel: 'low', requiresConfirmation: true, warnings: [ '⚠️ Le mot de passe n\'est PAS sauvegardé', '⚠️ NON récupérable en cas d\'oubli', '⚠️ À saisir à chaque utilisation' ], implementation: { useWebAuthn: false, useEncryption: true, usePlatformAuth: false, storageType: 'encrypted', requiresPassword: true } }, 'none': { mode: 'none', name: 'Aucune Sécurité', description: 'Stockage en clair sans aucune protection', securityLevel: 'critical', requiresConfirmation: true, warnings: [ '🚨 Clés stockées en clair', '🚨 Accès non protégé', '🚨 RISQUE ÉLEVÉ' ], implementation: { useWebAuthn: false, useEncryption: false, usePlatformAuth: false, storageType: 'plain' } } }; return configs[mode]; } /** * Vérifie si un mode nécessite une confirmation */ public requiresConfirmation(mode: SecurityMode): boolean { const config = this.getSecurityModeConfig(mode); return config.requiresConfirmation; } /** * Récupère les avertissements pour un mode */ public getWarnings(mode: SecurityMode): string[] { const config = this.getSecurityModeConfig(mode); return config.warnings; } /** * Vérifie si le mode actuel est sécurisé */ public async isCurrentModeSecure(): Promise { const currentMode = await this.getCurrentMode(); if (!currentMode) return false; const config = this.getSecurityModeConfig(currentMode); return config.securityLevel === 'high' || config.securityLevel === 'medium'; } /** * Récupère tous les modes disponibles */ public getAvailableModes(): SecurityMode[] { return ['proton-pass', 'os', 'browser', '2fa', 'none']; } /** * Récupère les modes recommandés (sécurisés) */ public getRecommendedModes(): SecurityMode[] { return ['proton-pass', 'os', 'browser']; } /** * Récupère les modes non recommandés (non sécurisés) */ public getNonRecommendedModes(): SecurityMode[] { return ['2fa', 'none']; } /** * Vérifie si un mode utilise WebAuthn */ public usesWebAuthn(mode: SecurityMode): boolean { const config = this.getSecurityModeConfig(mode); return config.implementation.useWebAuthn; } /** * Vérifie si un mode utilise le chiffrement */ public usesEncryption(mode: SecurityMode): boolean { const config = this.getSecurityModeConfig(mode); return config.implementation.useEncryption; } /** * Vérifie si un mode utilise l'authentificateur de plateforme */ public usesPlatformAuth(mode: SecurityMode): boolean { const config = this.getSecurityModeConfig(mode); return config.implementation.usePlatformAuth; } /** * Récupère le type de stockage pour un mode */ public getStorageType(mode: SecurityMode): 'encrypted' | 'plain' | 'hybrid' { const config = this.getSecurityModeConfig(mode); return config.implementation.storageType; } /** * Réinitialise le mode de sécurisation */ public async resetSecurityMode(): Promise { try { await this.database.deleteObject('security_settings', 'current_mode'); this.currentMode = null; secureLogger.info('Security mode reset', { component: 'SecurityModeService', operation: 'resetSecurityMode' }); } catch (error) { secureLogger.error('Failed to reset security mode', error as Error, { component: 'SecurityModeService', operation: 'resetSecurityMode' }); throw error; } } /** * Récupère l'historique des modes de sécurisation */ public async getSecurityModeHistory(): Promise { try { const history = await this.database.getObject('security_settings', 'mode_history') || []; return history; } catch (error) { secureLogger.error('Failed to retrieve security mode history', error as Error, { component: 'SecurityModeService', operation: 'getSecurityModeHistory' }); return []; } } /** * Ajoute une entrée à l'historique des modes */ private async addToHistory(mode: SecurityMode): Promise { try { const history = await this.getSecurityModeHistory(); history.unshift({ mode, timestamp: Date.now(), config: this.getSecurityModeConfig(mode) }); // Garder seulement les 10 dernières entrées if (history.length > 10) { history.splice(10); } await this.database.setObject('security_settings', 'mode_history', history); } catch (error) { secureLogger.error('Failed to add to security mode history', error as Error, { component: 'SecurityModeService', operation: 'addToHistory', mode }); } } }