02d89c58d2
PBKDF2 is implemented in Pascal rather than through javax.crypto SecretKeyFactory: PBEKeySpec takes a char[] and the provider decides how those chars become bytes, so a non-ASCII sync password would derive a different key than the browser and fail as 'wrong password'. AES-GCM does go through JNI - one call, hardware-backed, and WebCrypto's tag-appended layout is exactly what Cipher expects. The vector is generated with WebCrypto itself and uses a non-ASCII password on purpose; an ASCII-only vector would have hidden that bug. It records the derived key separately from the plaintext so a failure points at one stage instead of the whole chain.
67 lines
2.4 KiB
Markdown
67 lines
2.4 KiB
Markdown
# Vecteur de test — conteneur `pm-encrypted-export-v1`
|
|
|
|
`testvector.json` est produit par `make-testvector.js` avec **WebCrypto**, la
|
|
primitive exacte du navigateur. Sel et IV sont figés, donc le fichier est
|
|
reproductible : une différence signale un vrai changement de comportement, pas
|
|
du bruit.
|
|
|
|
> Le fichier de test réutilise un couple sel/IV fixe. C'est acceptable pour un
|
|
> vecteur, **jamais** dans l'application : réutiliser un IV avec la même clé
|
|
> détruit la sécurité de GCM.
|
|
|
|
## Paramètres
|
|
|
|
| | |
|
|
|---|---|
|
|
| Mot de passe | `sync-test-password-éàü` |
|
|
| KDF | PBKDF2-SHA256, 600 000 itérations, sel de 32 octets |
|
|
| Chiffrement | AES-256-GCM, IV de 12 octets, tag de 16 octets **en fin de `ciphertext`** |
|
|
|
|
Le mot de passe est **volontairement non-ASCII**. C'est le seul cas qui
|
|
distingue une implémentation correcte d'une implémentation approximative : Java
|
|
`PBEKeySpec` prend un `char[]` et laisse le fournisseur choisir l'encodage, ce
|
|
qui donne une clé différente pour `é`, `à`, `ü`. Un vecteur en pur ASCII aurait
|
|
laissé passer le bug.
|
|
|
|
## Valeurs attendues
|
|
|
|
Vérifier **dans cet ordre** — chaque étage isole une cause :
|
|
|
|
**1. Clé dérivée** (`DeriveKeyPBKDF2`, avant tout déchiffrement)
|
|
|
|
```
|
|
6bd7683ea78e163062f02681b03f2906fcf5a3a25025005af4e71982e6e2b286
|
|
```
|
|
|
|
Si elle diffère, le problème est dans PBKDF2 ou dans l'encodage du mot de passe
|
|
— surtout pas dans AES. Contrôler d'abord que le mot de passe est bien encodé
|
|
en UTF-8 (`sync-test-password-éàü` fait **25 octets**, pas 22 caractères).
|
|
|
|
**2. Texte clair** (`AesGcmDecrypt` puis `DecryptContainer`)
|
|
|
|
```
|
|
longueur UTF-8 : 572 octets
|
|
SHA-256 : ddaee44f8ac8374f1ece6d9ee2abd104d59cd283556f1c4c07afa95ae1dbd2a7
|
|
début : {"version":1,"exported_at":"2026-08-14T12:00:00.000Z","username":"test
|
|
```
|
|
|
|
Si la clé est bonne et que le déchiffrement échoue, chercher du côté de la
|
|
longueur du tag (128 **bits**) ou d'un tag qui aurait été séparé du corps —
|
|
WebCrypto le concatène, `javax.crypto` l'attend concaténé, il n'y a rien à
|
|
découper.
|
|
|
|
## Contenu
|
|
|
|
2 entrées, dont **une en corbeille** (`deleted: 1` avec son `deleted_at`), et
|
|
un dossier avec sa couleur. De quoi vérifier que le client mobile affiche la
|
|
corbeille séparément au lieu de la mélanger à la liste.
|
|
|
|
## Régénérer
|
|
|
|
```bash
|
|
node make-testvector.js > testvector.json
|
|
```
|
|
|
|
En PowerShell, la redirection ajoute un **BOM** qui rend le JSON illisible.
|
|
Utiliser `cmd`, ou écrire le fichier sans BOM.
|