feat(android): encryption, verified by a third implementation
Section 4 step 2. EncryptContainer produces the exact container the desktop writes: PBKDF2-SHA256, AES-256-GCM with the tag appended as WebCrypto does, a 32-byte salt and a 12-byte IV drawn per call from SecureRandom on Android and BCryptGenRandom on Windows - never Random, since a predictable salt or IV ruins the encryption that uses it and nothing in the output would show it. The check matters as much as the code. A round trip with itself only proves internal consistency, and it passed while the container carried two defects. Node - the same primitives as WebCrypto - found both by reading a container the phone had produced: - Delphi's base64 wraps at 76 characters; WebCrypto's never does. Lenient decoders accept it, but depending on their leniency is not a guarantee. - the accented literal in the check came out of the COMPILER already broken: this source has no byte-order mark, so Delphi reads it as ANSI. The defect was in the test rather than the encryption, and only the cross-check could tell those apart. The check runs at launch in DEBUG and leaves selfcheck.json in the private directory so it can be re-read from the PC. Also fixed on the way: TPath resolves to FMX.Objects.TPath - a drawing shape - because FMX.Objects comes later in the uses clause, and the error then talks about an unknown Combine rather than a name collision. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
+22
-4
@@ -356,10 +356,28 @@ d'interface d'édition.
|
||||
|
||||
1. ~~**`updated_at` dans `TVaultEntry`**~~ — **fait**, et déjà affiché comme
|
||||
*Modifié le* dans le détail. Rien n'était arbitrable sans lui.
|
||||
2. **AES-GCM en chiffrement.** On n'a que le déchiffrement, des deux côtés
|
||||
(JNI et CNG). Il faut aussi un sel de 32 octets et un IV de 12 octets tirés
|
||||
d'un générateur cryptographique — `SecureRandom` côté Android,
|
||||
`BCryptGenRandom` côté Windows. **Jamais** `Random`.
|
||||
2. ~~**AES-GCM en chiffrement**~~ — **fait le 2026-08-17**, et vérifié par une
|
||||
implémentation tierce. `EncryptContainer` produit le conteneur exact du
|
||||
poste ; sel de 32 octets et IV de 12 tirés de `SecureRandom` (Android) ou
|
||||
`BCryptGenRandom` (Windows), jamais `Random`.
|
||||
|
||||
**La vérification compte autant que le code.** Un aller-retour avec
|
||||
soi-même ne prouve que la cohérence interne : il passait alors que le
|
||||
conteneur portait deux défauts. C'est Node — mêmes primitives que WebCrypto
|
||||
— qui les a montrés en relisant un conteneur produit par le téléphone :
|
||||
|
||||
- le base64 de Delphi est **coupé à 76 caractères**, celui de WebCrypto ne
|
||||
l'est jamais. Les décodeurs tolérants l'acceptent, mais dépendre de leur
|
||||
tolérance n'est pas une garantie ; `B64NoWrap` produit désormais la même
|
||||
forme.
|
||||
- le littéral accentué du contrôle sortait **déjà abîmé du compilateur** —
|
||||
ce fichier n'a pas de marque d'ordre d'octets, et Delphi le lit en ANSI.
|
||||
Le défaut était dans le test, pas dans le chiffrement, mais seul le
|
||||
contrôle croisé pouvait le distinguer.
|
||||
|
||||
Le contrôle tourne au lancement en `DEBUG` et dépose `selfcheck.json` dans
|
||||
le répertoire privé, pour être relu depuis le PC :
|
||||
`adb shell run-as … cat …/files/selfcheck.json`.
|
||||
3. **`PUT` dans [sync.php](../server-php/sync.php)**, qui répond aujourd'hui
|
||||
405. Même authentification, `If-Match` obligatoire, **412** si l'ETag ne
|
||||
correspond plus, écriture atomique (fichier temporaire puis renommage —
|
||||
|
||||
Reference in New Issue
Block a user