Files
r-zakarya 3c1525e46f feat(android): end-to-end read path validated on device, add the container diagnostic
GET in 80 ms, decryption in 3893 ms, entries and trash counted, second call answers 304. try-open.js opens a container with Node so a failure can be attributed: a GCM tag that does not verify means wrong password OR altered file, and the app cannot tell which.
2026-08-15 00:31:01 +01:00

52 lines
2.0 KiB
JavaScript
Raw Permalink Blame History

This file contains invisible Unicode characters
This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
// Ouvre un conteneur pm-encrypted-export-v1 avec Node, pour distinguer un
// mauvais mot de passe d'un defaut du client Delphi.
//
// node try-open.js <fichier> <mot-de-passe>
//
// Utilise les memes primitives que le navigateur. Si Node y arrive et pas
// Delphi, le probleme est dans le client ; si les deux echouent, c'est le
// mot de passe.
const fs = require('node:fs');
const c = require('node:crypto');
const [, , file, pwd] = process.argv;
if (!file || pwd === undefined) {
console.error('usage: node try-open.js <fichier> <mot-de-passe>');
process.exit(2);
}
const raw = fs.readFileSync(file, 'utf8').replace(/^/, '');
let v;
try {
v = JSON.parse(raw);
} catch (e) {
console.error('Ce fichier n\'est pas du JSON : ' + e.message);
process.exit(1);
}
console.log('format : ' + v.format);
console.log('kdf : ' + v.kdf + ' / ' + v.kdf_iterations + ' iterations');
console.log('mot de passe : ' + pwd.length + ' caracteres, ' +
Buffer.byteLength(pwd, 'utf8') + ' octets UTF-8');
const salt = Buffer.from(v.kdf_salt, 'base64');
const iv = Buffer.from(v.iv, 'base64');
const ct = Buffer.from(v.ciphertext, 'base64');
const key = c.pbkdf2Sync(Buffer.from(pwd, 'utf8'), salt, v.kdf_iterations || 600000, 32, 'sha256');
console.log('cle derivee : ' + key.toString('hex'));
try {
const d = c.createDecipheriv('aes-256-gcm', key, iv);
d.setAuthTag(ct.subarray(ct.length - 16));
const pt = Buffer.concat([d.update(ct.subarray(0, ct.length - 16)), d.final()]).toString('utf8');
const obj = JSON.parse(pt);
const live = (obj.entries || []).filter(e => !e.deleted).length;
const trash = (obj.entries || []).filter(e => e.deleted).length;
console.log('==> OUVERT : ' + live + ' entrees, ' + trash + ' en corbeille');
console.log(' exporte le ' + (obj.exported_at || obj.snapshot_at || '?'));
} catch (e) {
console.log('==> ECHEC : ' + e.message);
console.log(' Le tag GCM ne verifie pas : mot de passe faux, ou fichier altere.');
}