@midasr/novashadowcookie
Version:
Module NPM natif pour le décryptage des données Chrome App-Bound Encryption, compatible avec Node.js et Bun
271 lines (235 loc) • 7.81 kB
JavaScript
// index.js - Point d'entrée principal du module chrome-decrypt-native
;
const path = require('path');
const fs = require('fs');
let nativeAddon;
try {
// Essayer de charger le module natif compilé
nativeAddon = require('./build/Release/chrome_decrypt_native.node');
} catch (error) {
try {
// Fallback vers le build Debug
nativeAddon = require('./build/Debug/chrome_decrypt_native.node');
} catch (debugError) {
throw new Error(
'Could not load chrome-decrypt-native binary. ' +
'Make sure to run "npm run build" first.\n' +
'Release error: ' + error.message + '\n' +
'Debug error: ' + debugError.message
);
}
}
/**
* Décrypte les données d'un profil Chrome/Edge/Brave
* @param {string} profilePath - Chemin vers le profil du navigateur
* @param {string} outputPath - Dossier de sortie pour les données extraites
* @returns {Promise<Object>} Résultats de l'extraction
*/
async function decryptChromeData(profilePath, outputPath) {
if (typeof profilePath !== 'string') {
throw new TypeError('profilePath must be a string');
}
if (typeof outputPath !== 'string') {
throw new TypeError('outputPath must be a string');
}
return nativeAddon.decryptChromeData(profilePath, outputPath);
}
/**
* Chiffre/déchiffre des données avec ChaCha20
* @param {Buffer} data - Données à traiter
* @param {Buffer} key - Clé de 32 bytes
* @param {Buffer} nonce - Nonce de 12 bytes
* @returns {Buffer} Données traitées
*/
function chaCha20Encrypt(data, key, nonce) {
if (!Buffer.isBuffer(data)) {
throw new TypeError('data must be a Buffer');
}
if (!Buffer.isBuffer(key)) {
throw new TypeError('key must be a Buffer');
}
if (!Buffer.isBuffer(nonce)) {
throw new TypeError('nonce must be a Buffer');
}
if (key.length !== 32) {
throw new Error('key must be exactly 32 bytes');
}
if (nonce.length !== 12) {
throw new Error('nonce must be exactly 12 bytes');
}
return nativeAddon.chaCha20Encrypt(data, key, nonce);
}
/**
* Extrait la clé maître chiffrée du fichier Local State
* @param {string} localStatePath - Chemin vers le fichier Local State
* @returns {Buffer} Clé chiffrée
*/
function getEncryptedMasterKey(localStatePath) {
if (typeof localStatePath !== 'string') {
throw new TypeError('localStatePath must be a string');
}
if (!fs.existsSync(localStatePath)) {
throw new Error('Local State file not found: ' + localStatePath);
}
return nativeAddon.getEncryptedMasterKey(localStatePath);
}
/**
* Décrypte des données AES-GCM
* @param {Buffer} key - Clé de déchiffrement
* @param {Buffer} encryptedData - Données chiffrées avec préfixe v20
* @returns {Buffer|null} Données déchiffrées ou null si échec
*/
function decryptGCM(key, encryptedData) {
if (!Buffer.isBuffer(key)) {
throw new TypeError('key must be a Buffer');
}
if (!Buffer.isBuffer(encryptedData)) {
throw new TypeError('encryptedData must be a Buffer');
}
return nativeAddon.decryptGCM(key, encryptedData);
}
/**
* Trouve automatiquement les profils Chrome/Edge/Brave
* @returns {string[]} Tableau des chemins vers les profils trouvés
*/
function findChromeProfiles() {
return nativeAddon.findChromeProfiles();
}
/**
* Trouve automatiquement les profils avec informations détaillées
* @returns {Object[]} Tableau d'informations sur les profils trouvés
*/
function findChromeProfilesDetailed() {
const profiles = findChromeProfiles();
return profiles.map(profilePath => {
const parts = profilePath.split(path.sep);
let browser = 'Unknown';
let profileName = 'Default';
// Déterminer le navigateur
if (profilePath.includes('Google\\Chrome')) {
browser = 'Chrome';
} else if (profilePath.includes('Microsoft\\Edge')) {
browser = 'Edge';
} else if (profilePath.includes('BraveSoftware\\Brave-Browser')) {
browser = 'Brave';
}
// Déterminer le nom du profil
const lastPart = parts[parts.length - 1];
if (lastPart !== 'Default') {
profileName = lastPart;
}
// Construire le chemin Local State
const userDataPath = path.dirname(profilePath);
const localStatePath = path.join(userDataPath, 'Local State');
return {
browser,
profileName,
profilePath,
localStatePath
};
});
}
/**
* Convertit un Buffer en string hexadécimale
* @param {Buffer} buffer - Buffer à convertir
* @returns {string} String hexadécimale
*/
function bufferToHex(buffer) {
if (!Buffer.isBuffer(buffer)) {
throw new TypeError('buffer must be a Buffer');
}
return nativeAddon.bufferToHex(buffer);
}
/**
* Convertit une string hexadécimale en Buffer
* @param {string} hex - String hexadécimale
* @returns {Buffer} Buffer correspondant
*/
function hexToBuffer(hex) {
if (typeof hex !== 'string') {
throw new TypeError('hex must be a string');
}
if (!/^[0-9a-fA-F]*$/.test(hex)) {
throw new Error('hex must contain only hexadecimal characters');
}
if (hex.length % 2 !== 0) {
throw new Error('hex string must have even length');
}
return nativeAddon.hexToBuffer(hex);
}
/**
* Valide qu'un chemin est un profil Chrome valide
* @param {string} profilePath - Chemin à valider
* @returns {boolean} true si le profil est valide
*/
function isValidChromeProfile(profilePath) {
if (typeof profilePath !== 'string') {
return false;
}
return nativeAddon.isValidChromeProfile(profilePath);
}
/**
* Obtient des informations sur un profil spécifique
* @param {string} profilePath - Chemin vers le profil
* @returns {Object|null} Informations sur le profil ou null si invalide
*/
function getProfileInfo(profilePath) {
if (!isValidChromeProfile(profilePath)) {
return null;
}
const detailed = findChromeProfilesDetailed();
return detailed.find(profile => profile.profilePath === profilePath) || null;
}
/**
* Génère une clé aléatoire
* @param {number} [size=32] - Taille de la clé en bytes
* @returns {Buffer} Buffer contenant la clé générée
*/
function generateKey(size = 32) {
if (typeof size !== 'number' || size <= 0) {
throw new TypeError('size must be a positive number');
}
return nativeAddon.generateKey(size);
}
/**
* Génère un nonce aléatoire
* @param {number} [size=12] - Taille du nonce en bytes
* @returns {Buffer} Buffer contenant le nonce généré
*/
function generateNonce(size = 12) {
if (typeof size !== 'number' || size <= 0) {
throw new TypeError('size must be a positive number');
}
return nativeAddon.generateNonce(size);
}
// Alias pour compatibilité
const encrypt = chaCha20Encrypt;
const decrypt = decryptChromeData;
// Métadonnées du module
const version = nativeAddon.version;
const supportedBrowsers = nativeAddon.supportedBrowsers;
// Exports CommonJS
module.exports = {
// Fonctions principales
decryptChromeData,
chaCha20Encrypt,
getEncryptedMasterKey,
decryptGCM,
findChromeProfiles,
findChromeProfilesDetailed,
// Utilitaires
bufferToHex,
hexToBuffer,
isValidChromeProfile,
getProfileInfo,
generateKey,
generateNonce,
// Alias
encrypt,
decrypt,
// Métadonnées
version,
supportedBrowsers
};
// Support ESM (export named et default)
module.exports.default = module.exports;