/** * 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 * NOTE: Le mode de sécurité est stocké uniquement avec la clé PBKDF2, pas dans un store séparé */ import { secureLogger } from './secure-logger'; import Database from './database.service'; export type SecurityMode = 'proton-pass' | 'os' | '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'; requiresOTP?: boolean; requiresPassword?: boolean; }; } export class SecurityModeService { private static instance: SecurityModeService; private currentMode: SecurityMode | null = null; private constructor() { // N'instancier pas Database ici, il sera récupéré via getInstance() quand nécessaire } public static getInstance(): SecurityModeService { if (!SecurityModeService.instance) { SecurityModeService.instance = new SecurityModeService(); } return SecurityModeService.instance; } /** * Récupère le mode de sécurisation actuel * NOTE: Le mode est stocké uniquement en mémoire, dérivé de la clé PBKDF2 stockée */ public async getCurrentMode(): Promise { if (this.currentMode) { return this.currentMode; } // Le mode de sécurité n'est pas stocké en base, il est dérivé de la clé PBKDF2 // Ici on retourne null si aucun mode n'est en mémoire // Le mode sera défini lors de la génération de la clé PBKDF2 secureLogger.info('No security mode in memory (will be set when PBKDF2 key is generated)', { component: 'SecurityModeService', operation: 'getCurrentMode' }); return null; } /** * Définit le mode de sécurisation * NOTE: Le mode de sécurité est stocké uniquement avec la clé PBKDF2, pas dans un store séparé */ public async setSecurityMode(mode: SecurityMode): Promise { try { const modeConfig = this.getSecurityModeConfig(mode); // Stocker uniquement en mémoire 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 }); // NE PAS FAIRE DE FALLBACK - échouer complètement throw error; } } /** * 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' } }, '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: 'Chiffrement avec une clé déterminée en dur (non sécurisé)', securityLevel: 'critical', requiresConfirmation: true, warnings: [ '🚨 Clé de chiffrement en dur', '🚨 Accès non protégé', '🚨 RISQUE ÉLEVÉ' ], implementation: { useWebAuthn: false, useEncryption: true, usePlatformAuth: false, storageType: 'encrypted', requiresPassword: false } } }; 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', 'otp', '2fa', 'password', 'none']; } /** * Récupère les modes recommandés (sécurisés) */ public getRecommendedModes(): SecurityMode[] { return ['proton-pass', 'os', 'otp']; } /** * 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 { const database = await Database.getInstance(); await 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 database = await Database.getInstance(); const history = await 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); } const database = await Database.getInstance(); await database.addObject({ storeName: 'security_settings', key: 'mode_history', object: history }); } catch (error) { secureLogger.error('Failed to add to security mode history', error as Error, { component: 'SecurityModeService', operation: 'addToHistory', mode }); } } }