From 4042025e22db8267a60e641a259b7aa2dbc58f57 Mon Sep 17 00:00:00 2001 From: NicolasCantu Date: Sun, 26 Oct 2025 03:06:38 +0100 Subject: [PATCH] fix: add missing methods to StorageService and SecureCredentialsService - Added retrieveKeyFromBrowser(), retrievePlainKey(), retrieveEncryptedKey(), storeEncryptedKey() to StorageService - Added promptForPassword() method to SecureCredentialsService - Fixed error handling in storage.service.ts --- src/services/credentials/storage.service.ts | 114 +++++++++++++++++++- src/services/secure-credentials.service.ts | 14 +++ 2 files changed, 127 insertions(+), 1 deletion(-) diff --git a/src/services/credentials/storage.service.ts b/src/services/credentials/storage.service.ts index 0b91770..13a437f 100644 --- a/src/services/credentials/storage.service.ts +++ b/src/services/credentials/storage.service.ts @@ -126,6 +126,117 @@ export class StorageService { } } + /** + * Récupère une clé depuis le gestionnaire de mots de passe du navigateur + */ + async retrieveKeyFromBrowser(): Promise { + try { + const credentials = await navigator.credentials.get({ + password: true, + mediation: 'required' as CredentialMediationRequirement + }); + + if (credentials && 'password' in credentials) { + return credentials.password || null; + } + + return null; + } catch (error) { + secureLogger.error('Failed to retrieve key from browser', { + component: 'StorageService', + operation: 'retrieveKeyFromBrowser', + error: error instanceof Error ? error.message : String(error) + }); + return null; + } + } + + /** + * Récupère une clé en clair depuis IndexedDB + */ + async retrievePlainKey(): Promise { + try { + const db = await this.openDatabase(); + const transaction = db.transaction([this.storeName], 'readonly'); + const store = transaction.objectStore(this.storeName); + + const result = await new Promise((resolve, reject) => { + const request = store.get('plain-pbkdf2-key'); + request.onsuccess = () => resolve(request.result || null); + request.onerror = () => reject(request.error); + }); + + return result; + } catch (error) { + secureLogger.error('Failed to retrieve plain key', { + component: 'StorageService', + operation: 'retrievePlainKey', + error: error instanceof Error ? error.message : String(error) + }); + return null; + } + } + + /** + * Récupère une clé chiffrée depuis IndexedDB + */ + async retrieveEncryptedKey(): Promise { + try { + const db = await this.openDatabase(); + const transaction = db.transaction([this.storeName], 'readonly'); + const store = transaction.objectStore(this.storeName); + + const result = await new Promise((resolve, reject) => { + const request = store.get('encrypted-pbkdf2-key'); + request.onsuccess = () => resolve(request.result || null); + request.onerror = () => reject(request.error); + }); + + return result; + } catch (error) { + secureLogger.error('Failed to retrieve encrypted key', { + component: 'StorageService', + operation: 'retrieveEncryptedKey', + error: error instanceof Error ? error.message : String(error) + }); + return null; + } + } + + /** + * Stocke une clé chiffrée dans IndexedDB + */ + async storeEncryptedKey(encryptedKey: string, securityMode?: string): Promise { + try { + secureLogger.info('Storing encrypted key', { + component: 'StorageService', + operation: 'storeEncryptedKey' + }); + + const db = await this.openDatabase(); + const transaction = db.transaction([this.storeName], 'readwrite'); + const store = transaction.objectStore(this.storeName); + + await new Promise((resolve, reject) => { + const request = store.put(encryptedKey, 'encrypted-pbkdf2-key'); + request.onsuccess = () => resolve(); + request.onerror = () => reject(request.error); + }); + + secureLogger.info('Encrypted key stored successfully', { + component: 'StorageService', + operation: 'storeEncryptedKey' + }); + } catch (error) { + secureLogger.error('Failed to store encrypted key', { + component: 'StorageService', + operation: 'storeEncryptedKey', + error: error instanceof Error ? error.message : String(error) + }); + throw error; + } + } + /** * Ouvre la base de données IndexedDB */ @@ -134,7 +245,8 @@ export class StorageService { const request = indexedDB.open(this.dbName, this.dbVersion); request.onerror = () => { - secureLogger.error('Failed to open IndexedDB', new Error('Database open failed'), { + const error = new Error('Database open failed'); + secureLogger.error('Failed to open IndexedDB', error, { component: 'StorageService', operation: 'openDatabase' }); diff --git a/src/services/secure-credentials.service.ts b/src/services/secure-credentials.service.ts index 2cb5484..d21687a 100644 --- a/src/services/secure-credentials.service.ts +++ b/src/services/secure-credentials.service.ts @@ -785,6 +785,20 @@ QR Code URL: ${qrUrl}`); return this.clearCredentials(); } + /** + * Demande un mot de passe à l'utilisateur + */ + private async promptForPassword(): Promise { + return new Promise((resolve, reject) => { + const password = prompt('Entrez un mot de passe pour chiffrer la clé PBKDF2:'); + if (password) { + resolve(password); + } else { + reject(new Error('Password prompt cancelled')); + } + }); + } + /** * Valide la force d'un mot de passe */