fix(sync): la synchronisation dupliquait l'historique des mots de passe
L'instantane transporte le mot de passe EN CLAIR, et encryptImportEntry le re-chiffre avec un IV neuf : le chiffre differe donc toujours, meme quand le mot de passe n'a pas bouge. Or le serveur decide d'ecrire une version dans l'historique en comparant les chiffres (`encrypted_password <> :newenc`) - il voyait une difference la ou il n'y en avait aucune, et chaque synchronisation qui redescendait une entree y deposait un doublon date du jour. L'historique montrait la meme valeur deux fois, a des jours d'ecart. Le serveur ne peut pas trancher, il ne voit que du chiffre. Seul le client connait les deux clairs : il compare, et rend le chiffre d'origine quand ils sont egaux - ce que le commentaire du handler appelle deja "JS reuses originalEncrypted bit-for-bit". Trouve en deroulant la serie H sur le telephone. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
@@ -540,6 +540,29 @@ async function applyRemoteSnapshot(remote) {
|
|||||||
if (!remoteWins) continue;
|
if (!remoteWins) continue;
|
||||||
try {
|
try {
|
||||||
const enc = await encryptImportEntry(r);
|
const enc = await encryptImportEntry(r);
|
||||||
|
// LE MOT DE PASSE INCHANGÉ GARDE SON CHIFFRÉ, BIT POUR BIT.
|
||||||
|
//
|
||||||
|
// L'instantané transporte le clair, et encryptImportEntry le
|
||||||
|
// re-chiffre avec un IV neuf : le chiffré diffère donc TOUJOURS,
|
||||||
|
// même quand le mot de passe n'a pas bougé. Or le serveur décide
|
||||||
|
// d'écrire une version dans l'historique en comparant les
|
||||||
|
// chiffrés (`encrypted_password <> :newenc`) — il voyait une
|
||||||
|
// différence là où il n'y en avait aucune, et chaque
|
||||||
|
// synchronisation qui redescendait une entrée y déposait un
|
||||||
|
// doublon daté du jour.
|
||||||
|
//
|
||||||
|
// Le serveur ne peut pas trancher : il ne voit que du chiffré.
|
||||||
|
// Seul le client connaît les deux clairs. On compare ici, et on
|
||||||
|
// rend son chiffré d'origine quand ils sont égaux — ce que le
|
||||||
|
// commentaire du handler appelle déjà « JS reuses
|
||||||
|
// originalEncrypted bit-for-bit ».
|
||||||
|
if (local.encrypted_password && local.iv) {
|
||||||
|
const before = await decryptPwd(local.encrypted_password, local.iv);
|
||||||
|
if (before !== '[ERROR]' && before === (r.password || '')) {
|
||||||
|
enc.encrypted_password = local.encrypted_password;
|
||||||
|
enc.iv = local.iv;
|
||||||
|
}
|
||||||
|
}
|
||||||
// PUT keeps the existing id but accepts the encrypted blobs.
|
// PUT keeps the existing id but accepts the encrypted blobs.
|
||||||
// template + uuid not touched here (server preserves columns
|
// template + uuid not touched here (server preserves columns
|
||||||
// when fields aren't in body — uuid is immutable anyway).
|
// when fields aren't in body — uuid is immutable anyway).
|
||||||
|
|||||||
Reference in New Issue
Block a user