From c63fe484205af9cb647ebea3c4f17904aee2c36c Mon Sep 17 00:00:00 2001 From: NicolasCantu Date: Wed, 29 Oct 2025 13:13:52 +0100 Subject: [PATCH] fix: encrypt device before saving in saveDeviceInDatabase MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit **Motivations :** - saveDeviceInDatabase() sauvegardait le device en clair, écrasant le wallet chiffré - wallet-setup.ts sauvegarde le device chiffré avec encrypted_device et encrypted_wallet - Après updateDeviceBlockHeight(), le wallet était écrasé par un wallet en clair - Violation de sécurité: le wallet ne doit jamais être stocké en clair **Modifications :** - Modification de saveDeviceInDatabase() pour chiffrer le device avant sauvegarde - Récupération de la clé PBKDF2 pour chiffrer le device - Préservation de encrypted_wallet lors de la sauvegarde - Utilisation du même format que wallet-setup.ts (encrypted_device + encrypted_wallet) - Amélioration de la gestion des erreurs avec logs explicites **Pages affectées :** - src/services/service.ts (saveDeviceInDatabase chiffre maintenant le device) --- src/services/service.ts | 87 +++++++++++++++++++++++++++++++++++++---- 1 file changed, 80 insertions(+), 7 deletions(-) diff --git a/src/services/service.ts b/src/services/service.ts index 87729b3..94b6981 100755 --- a/src/services/service.ts +++ b/src/services/service.ts @@ -1815,20 +1815,93 @@ export default class Services { } async saveDeviceInDatabase(device: Device): Promise { - const db = await Database.getInstance(); - const walletStore = DATABASE_CONFIG.stores.wallet.name; try { - const prevDevice = await this.getDeviceFromDatabase(); - if (prevDevice) { - await db.deleteObject(walletStore, '1'); + // Récupérer la clé PBKDF2 pour chiffrer le device + const { SecureCredentialsService } = await import('./secure-credentials.service'); + const secureCredentialsService = SecureCredentialsService.getInstance(); + + // Trouver le mode de sécurité qui fonctionne + const allSecurityModes = ['none', 'otp', 'password', 'os', 'proton-pass']; + let pbkdf2Key: string | null = null; + let workingMode: string | null = null; + + for (const mode of allSecurityModes) { + try { + const hasKey = await secureCredentialsService.hasPBKDF2Key(mode as any); + if (hasKey) { + const key = await secureCredentialsService.retrievePBKDF2Key(mode as any); + if (key) { + pbkdf2Key = key; + workingMode = mode; + break; + } + } + } catch (e) { + // Continue to next mode + } } + + if (!pbkdf2Key) { + throw new Error('Failed to retrieve PBKDF2 key - cannot encrypt device'); + } + + // Chiffrer le device + const { EncryptionService } = await import('./encryption.service'); + const encryptionService = EncryptionService.getInstance(); + const deviceString = JSON.stringify(device); + const encryptedDevice = await encryptionService.encrypt(deviceString, pbkdf2Key); + + // Récupérer le wallet existant pour préserver encrypted_wallet + let encryptedWallet: string | undefined = undefined; + + // Récupérer le wallet chiffré depuis la base de données directement + const dbTemp = await new Promise((resolve, reject) => { + const request = indexedDB.open(DATABASE_CONFIG.name, DATABASE_CONFIG.version); + request.onsuccess = () => resolve(request.result); + request.onerror = () => reject(request.error); + }); + + const walletStoreName = DATABASE_CONFIG.stores.wallet.name; + const walletData = await new Promise((resolve, reject) => { + const tx = dbTemp.transaction(walletStoreName, 'readonly'); + const store = tx.objectStore(walletStoreName); + const getRequest = store.get('1'); + getRequest.onsuccess = () => resolve(getRequest.result); + getRequest.onerror = () => reject(getRequest.error); + }); + + if (walletData && walletData.encrypted_wallet) { + encryptedWallet = walletData.encrypted_wallet; + } + + // Sauvegarder avec le format chiffré + const db = await Database.getInstance(); + const walletStore = DATABASE_CONFIG.stores.wallet.name; + + // Supprimer l'ancien wallet si nécessaire (utiliser put au lieu de delete/add pour éviter les problèmes de timing) + await db.deleteObject(walletStore, '1'); + + // Sauvegarder le wallet chiffré + const walletObject: any = { + pre_id: '1', + encrypted_device: encryptedDevice + }; + + // Préserver encrypted_wallet s'il existe + if (encryptedWallet) { + walletObject.encrypted_wallet = encryptedWallet; + } + await db.addObject({ storeName: walletStore, - object: { pre_id: '1', device }, + object: walletObject, key: null, }); + + console.log('✅ Device saved to database with encryption'); } catch (e) { - console.error(e); + console.error('❌ Error saving device to database:', e); + throw e; } }