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
This commit is contained in:
NicolasCantu 2025-10-26 03:06:38 +01:00
parent 0b92af0905
commit 4042025e22
2 changed files with 127 additions and 1 deletions

View File

@ -126,6 +126,117 @@ export class StorageService {
} }
} }
/**
* Récupère une clé depuis le gestionnaire de mots de passe du navigateur
*/
async retrieveKeyFromBrowser(): Promise<string | null> {
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<string | null> {
try {
const db = await this.openDatabase();
const transaction = db.transaction([this.storeName], 'readonly');
const store = transaction.objectStore(this.storeName);
const result = await new Promise<string | null>((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<string | null> {
try {
const db = await this.openDatabase();
const transaction = db.transaction([this.storeName], 'readonly');
const store = transaction.objectStore(this.storeName);
const result = await new Promise<string | null>((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<void> {
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<void>((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 * Ouvre la base de données IndexedDB
*/ */
@ -134,7 +245,8 @@ export class StorageService {
const request = indexedDB.open(this.dbName, this.dbVersion); const request = indexedDB.open(this.dbName, this.dbVersion);
request.onerror = () => { 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', component: 'StorageService',
operation: 'openDatabase' operation: 'openDatabase'
}); });

View File

@ -785,6 +785,20 @@ QR Code URL: ${qrUrl}`);
return this.clearCredentials(); return this.clearCredentials();
} }
/**
* Demande un mot de passe à l'utilisateur
*/
private async promptForPassword(): Promise<string> {
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 * Valide la force d'un mot de passe
*/ */