74 lines
2.1 KiB
TypeScript
74 lines
2.1 KiB
TypeScript
import { createCipheriv, createDecipheriv, randomBytes, pbkdf2Sync } from 'crypto';
|
|
|
|
// Clé de chiffrement dérivée de la clé Supabase
|
|
const deriveKey = (): Buffer => {
|
|
const salt = process.env.SUPABASE_ANON_KEY || 'default-salt';
|
|
return pbkdf2Sync(salt, 'mes-budgets-participatifs', 100000, 32, 'sha256');
|
|
};
|
|
|
|
export const encryptionService = {
|
|
/**
|
|
* Chiffre une valeur avec AES-256-GCM
|
|
*/
|
|
encrypt(value: string): string {
|
|
if (!value) return '';
|
|
|
|
const key = deriveKey();
|
|
const iv = randomBytes(16);
|
|
const cipher = createCipheriv('aes-256-gcm', key, iv);
|
|
|
|
let encrypted = cipher.update(value, 'utf8', 'hex');
|
|
encrypted += cipher.final('hex');
|
|
|
|
const authTag = cipher.getAuthTag();
|
|
|
|
// Format: iv:authTag:encryptedData
|
|
return `${iv.toString('hex')}:${authTag.toString('hex')}:${encrypted}`;
|
|
},
|
|
|
|
/**
|
|
* Déchiffre une valeur chiffrée avec AES-256-GCM
|
|
*/
|
|
decrypt(encryptedValue: string): string {
|
|
if (!encryptedValue) return '';
|
|
|
|
try {
|
|
const parts = encryptedValue.split(':');
|
|
if (parts.length !== 3) {
|
|
throw new Error('Format de chiffrement invalide');
|
|
}
|
|
|
|
const [ivHex, authTagHex, encryptedData] = parts;
|
|
const key = deriveKey();
|
|
const iv = Buffer.from(ivHex, 'hex');
|
|
const authTag = Buffer.from(authTagHex, 'hex');
|
|
|
|
const decipher = createDecipheriv('aes-256-gcm', key, iv);
|
|
decipher.setAuthTag(authTag);
|
|
|
|
let decrypted = decipher.update(encryptedData, 'hex', 'utf8');
|
|
decrypted += decipher.final('utf8');
|
|
|
|
return decrypted;
|
|
} catch (error) {
|
|
console.error('Erreur lors du déchiffrement:', error);
|
|
return '';
|
|
}
|
|
},
|
|
|
|
/**
|
|
* Vérifie si une valeur est chiffrée
|
|
*/
|
|
isEncrypted(value: string): boolean {
|
|
return Boolean(value && value.includes(':') && value.split(':').length === 3);
|
|
},
|
|
|
|
/**
|
|
* Masque une valeur pour l'affichage
|
|
*/
|
|
mask(value: string, maskChar: string = '•'): string {
|
|
if (!value) return '';
|
|
return maskChar.repeat(Math.min(value.length, 8));
|
|
}
|
|
};
|