diff --git a/android-client/README.md b/android-client/README.md index 441efb4..6f959ae 100644 --- a/android-client/README.md +++ b/android-client/README.md @@ -42,6 +42,35 @@ ce qui est acceptable et compréhensible pour l'utilisateur. > jamais toucher le disque autrement que chiffré sous la clé du Keystore, et la > sauvegarde automatique Android doit être désactivée pour l'application. +## Chaîne validée de bout en bout + +Sur appareil : `GET` authentifié (80 ms) → déchiffrement (3893 ms) → lecture du +JSON, entrées vivantes et corbeille comptées séparément. Second appel : **304**, +rien de retéléchargé, rien de re-déchiffré. + +**L'ETag n'est retenu que si le déchiffrement a réussi.** Le conserver dès la +réception paraît naturel et c'est un piège : après un échec, le prochain appel +répond 304 et l'application se retrouve sans données tout en se croyant à jour. +L'ETag appartient au **clair détenu**, pas au téléchargement. + +## Diagnostiquer un échec de déchiffrement + +`try-open.js` ouvre un conteneur avec Node, donc avec les primitives du +navigateur : + +```bash +node try-open.js +``` + +Il sépare deux causes que l'application ne peut pas distinguer — un tag GCM qui +ne vérifie pas signifie *mot de passe faux OU fichier altéré*, sans plus. Si +Node ouvre le fichier et pas le client, le défaut est dans le client. + +> Le mot de passe de sync n'est **pas** le mot de passe maître. Il n'est affiché +> nulle part : `prefs.bin` le garde chiffré par DPAPI, et l'application sait +> seulement le définir. En cas d'oubli, le redéfinir puis relancer un sync pour +> rechiffrer l'instantané distant. + ## Fichiers | | | diff --git a/android-client/try-open.js b/android-client/try-open.js new file mode 100644 index 0000000..1b0768d --- /dev/null +++ b/android-client/try-open.js @@ -0,0 +1,51 @@ +// 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 +// +// 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 '); + 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.'); +} diff --git a/pmserverApk.deployproj b/pmserverApk.deployproj index 3ea86c3..05c8f3e 100644 --- a/pmserverApk.deployproj +++ b/pmserverApk.deployproj @@ -51,6 +51,15 @@ True + + pmserverApk\res\drawable-anydpi-v31\ + splash_vector.xml + Android_VectorizedSplashV31 + 1 + + + True + pmserverApk\res\values-v31\ styles.xml @@ -78,6 +87,15 @@ True + + pmserverApk\res\drawable\ + ic_launcher_background.xml + Android_AdaptiveIconBackground + 1 + + + True + pmserverApk\res\drawable-hdpi\ ic_launcher.png @@ -87,6 +105,24 @@ True + + pmserverApk\res\drawable-normal\ + splash_image.png + Android_SplashImage470 + 1 + + + True + + + pmserverApk\res\drawable-xxhdpi\ + ic_notification.png + Android_NotificationIcon72 + 1 + + + True + pmserverApk\res\drawable\ ic_launcher_monochrome.xml @@ -105,6 +141,42 @@ True + + pmserverApk\res\drawable-xxhdpi\ + ic_launcher.png + Android_LauncherIcon144 + 1 + + + True + + + pmserverApk\res\drawable-xxxhdpi\ + ic_launcher.png + Android_LauncherIcon192 + 1 + + + True + + + pmserverApk\res\drawable-anydpi-v24\ + ic_notification.xml + Android_VectorizedNotificationIcon + 1 + + + True + + + pmserverApk\res\drawable-xhdpi\ + ic_launcher.png + Android_LauncherIcon96 + 1 + + + True + pmserverApk\res\drawable-xlarge\ splash_image.png @@ -114,6 +186,24 @@ True + + pmserverApk\res\drawable-night-anydpi-v31\ + splash_vector.xml + Android_VectorizedSplashV31Dark + 1 + + + True + + + pmserverApk\ + AndroidManifest.xml + ProjectAndroidManifest + 1 + + + True + pmserverApk\res\drawable\ splash_vector.xml @@ -123,6 +213,15 @@ True + + pmserverApk\res\values\ + styles.xml + AndroidSplashStyles + 1 + + + True + pmserverApk\res\drawable-xhdpi\ ic_notification.png @@ -141,6 +240,16 @@ True + + pmserverApk\library\lib\armeabi-v7a\ + libpmserverApk.so + ProjectOutput + 1 + + + True + True + pmserverApk\res\drawable\ ic_launcher_foreground.xml @@ -159,6 +268,33 @@ True + + pmserverApk\library\lib\mips\ + libpmserverApk.so + AndroidLibnativeMipsFile + 1 + + + True + + + pmserverApk\res\drawable-mdpi\ + ic_notification.png + Android_NotificationIcon24 + 1 + + + True + + + pmserverApk\res\drawable-small\ + splash_image.png + Android_SplashImage426 + 1 + + + True + pmserverApk\res\drawable-anydpi-v33\ ic_launcher.xml @@ -186,6 +322,15 @@ True + + pmserverApk\classes\ + pmserverApk.classes + AndroidClasses + 64 + + + True + pmserverApk\res\drawable-anydpi-v26\ ic_launcher.xml @@ -213,151 +358,6 @@ True - - pmserverApk\res\drawable-anydpi-v31\ - splash_vector.xml - Android_VectorizedSplashV31 - 1 - - - True - - - pmserverApk\res\drawable\ - ic_launcher_background.xml - Android_AdaptiveIconBackground - 1 - - - True - - - pmserverApk\res\drawable-normal\ - splash_image.png - Android_SplashImage470 - 1 - - - True - - - pmserverApk\res\drawable-xxhdpi\ - ic_notification.png - Android_NotificationIcon72 - 1 - - - True - - - pmserverApk\res\drawable-xxhdpi\ - ic_launcher.png - Android_LauncherIcon144 - 1 - - - True - - - pmserverApk\res\drawable-xxxhdpi\ - ic_launcher.png - Android_LauncherIcon192 - 1 - - - True - - - pmserverApk\res\drawable-anydpi-v24\ - ic_notification.xml - Android_VectorizedNotificationIcon - 1 - - - True - - - pmserverApk\res\drawable-xhdpi\ - ic_launcher.png - Android_LauncherIcon96 - 1 - - - True - - - pmserverApk\res\drawable-night-anydpi-v31\ - splash_vector.xml - Android_VectorizedSplashV31Dark - 1 - - - True - - - pmserverApk\ - AndroidManifest.xml - ProjectAndroidManifest - 1 - - - True - - - pmserverApk\res\values\ - styles.xml - AndroidSplashStyles - 1 - - - True - - - pmserverApk\library\lib\armeabi-v7a\ - libpmserverApk.so - ProjectOutput - 1 - - - True - True - - - pmserverApk\library\lib\mips\ - libpmserverApk.so - AndroidLibnativeMipsFile - 1 - - - True - - - pmserverApk\res\drawable-mdpi\ - ic_notification.png - Android_NotificationIcon24 - 1 - - - True - - - pmserverApk\res\drawable-small\ - splash_image.png - Android_SplashImage426 - 1 - - - True - - - pmserverApk\classes\ - pmserverApk.classes - AndroidClasses - 64 - - - True - pmserverApk\res\drawable-night-anydpi-v21\ splash_vector.xml @@ -369,360 +369,7 @@ - - - pmserverApk\res\drawable-anydpi-v26\ - ic_launcher.xml - Android_AdaptiveIcon - 1 - - - True - - - pmserverApk\res\drawable-hdpi\ - ic_launcher.png - Android_LauncherIcon72 - 1 - - - True - - - pmserverApk\res\drawable-mdpi\ - ic_launcher.png - Android_LauncherIcon48 - 1 - - - True - - - pmserverApk\res\drawable-xxhdpi\ - ic_launcher.png - Android_LauncherIcon144 - 1 - - - True - - - pmserverApk\res\drawable-large\ - splash_image.png - Android_SplashImage640 - 1 - - - True - - - pmserverApk\res\drawable\ - ic_launcher_monochrome.xml - Android_AdaptiveIconMonochrome - 1 - - - True - - - pmserverApk\res\values-v31\ - styles.xml - AndroidSplashStylesV31 - 1 - - - True - - - pmserverApk\res\drawable-xxxhdpi\ - ic_notification.png - Android_NotificationIcon96 - 1 - - - True - - - pmserverApk\library\lib\mips\ - libpmserverApk.so - AndroidLibnativeMipsFile - 1 - - - True - - - pmserverApk\res\drawable\ - splash_vector.xml - Android_VectorizedSplash - 1 - - - True - - - pmserverApk\library\lib\armeabi-v7a\ - libpmserverApk.so - AndroidLibnativeArmeabiv7aFile - 1 - - - True - - - pmserverApk\res\drawable-ldpi\ - ic_launcher.png - Android_LauncherIcon36 - 1 - - - True - - - pmserverApk\res\drawable-night-anydpi-v31\ - splash_vector.xml - Android_VectorizedSplashV31Dark - 1 - - - True - - - pmserverApk\res\values\ - styles.xml - AndroidSplashStyles - 1 - - - True - - - pmserverApk\res\drawable-anydpi-v24\ - ic_notification.xml - Android_VectorizedNotificationIcon - 1 - - - True - - - pmserverApk\res\drawable\ - ic_launcher_foreground.xml - Android_AdaptiveIconForeground - 1 - - - True - - - pmserverApk\res\drawable\ - ic_launcher_background.xml - Android_AdaptiveIconBackground - 1 - - - True - - - pmserverApk\res\drawable-anydpi-v33\ - ic_launcher.xml - Android_AdaptiveIconV33 - 1 - - - True - - - pmserverApk\classes\ - pmserverApk.classes - AndroidClasses - 64 - - - True - - - pmserverApk\res\drawable-anydpi-v31\ - splash_vector.xml - Android_VectorizedSplashV31 - 1 - - - True - - - pmserverApk\res\drawable-night-anydpi-v21\ - splash_vector.xml - Android_VectorizedSplashDark - 1 - - - True - - - pmserverApk\ - AndroidManifest.xml - ProjectAndroidManifest - 1 - - - True - - - pmserverApk\res\drawable-xxxhdpi\ - ic_launcher.png - Android_LauncherIcon192 - 1 - - - True - - - pmserverApk\res\values-night-v21\ - colors.xml - Android_ColorsDark - 1 - - - True - - - pmserverApk\res\drawable-xhdpi\ - ic_notification.png - Android_NotificationIcon48 - 1 - - - True - - - pmserverApk\res\drawable-anydpi-v21\ - splash_image_def.xml - AndroidSplashImageDefV21 - 1 - - - True - - - pmserverApk\library\lib\armeabi\ - libpmserverApk.so - AndroidLibnativeArmeabiFile - 1 - - - True - - - pmserverApk\res\values\ - colors.xml - Android_Colors - 1 - - - True - - - pmserverApk\res\drawable\ - splash_image_def.xml - AndroidSplashImageDef - 1 - - - True - - - pmserverApk\res\drawable-hdpi\ - ic_notification.png - Android_NotificationIcon36 - 1 - - - True - - - pmserverApk\res\drawable-xhdpi\ - ic_launcher.png - Android_LauncherIcon96 - 1 - - - True - - - pmserverApk\res\drawable-mdpi\ - ic_notification.png - Android_NotificationIcon24 - 1 - - - True - - - pmserverApk\res\drawable-xlarge\ - splash_image.png - Android_SplashImage960 - 1 - - - True - - - pmserverApk\res\drawable-small\ - splash_image.png - Android_SplashImage426 - 1 - - - True - - - pmserverApk\res\values\ - strings.xml - Android_Strings - 1 - - - True - - - pmserverApk\res\values-v21\ - styles.xml - AndroidSplashStylesV21 - 1 - - - True - - - pmserverApk\library\lib\arm64-v8a\ - libpmserverApk.so - ProjectOutput - 1 - - - True - True - - - pmserverApk\res\drawable-xxhdpi\ - ic_notification.png - Android_NotificationIcon72 - 1 - - - True - - - pmserverApk\res\drawable-normal\ - splash_image.png - Android_SplashImage470 - 1 - - - True - - +