Tout format de fichier chiffré doit répondre à une question discrète : qu'est-ce qui empêche un attaquant de modifier les parties qui ne sont pas secrètes ? Le format de fichier de StenVault, CVEF, en a appris la réponse à la dure — et la v1.4 est le correctif.
Un fichier CVEF est un petit en-tête, un bloc de métadonnées JSON et la charge utile chiffrée. Les métadonnées déclarent la suite cryptographique : l'algorithme, la clé de fichier encapsulée et — depuis la v1.3 — une signature hybride (Ed25519 + ML-DSA-65) qui prouve qui a scellé le fichier.
La faille : des métadonnées que personne n'authentifiait
Jusqu'à la v1.3, ces métadonnées JSON n'étaient ni chiffrées ni authentifiées. Le tag AES-256-GCM couvrait la charge utile, pas l'en-tête qui l'entourait. Pour la plupart des champs, cela échoue de manière sûre — modifiez la clé encapsulée et le déchiffrement produit simplement du charabia puis s'interrompt. Un champ n'échouait pas de manière sûre : la version.
Les signatures dans CVEF ne concernent que les métadonnées — elles ne sont pas nécessaires pour déchiffrer le fichier. Ainsi, un attaquant disposant d'un accès en écriture à un fichier stocké pouvait prendre un fichier v1.3 signé, retirer le champ `signatureParams` et changer la `version` de `1.3` à `1.2`. Le résultat est un fichier v1.2 parfaitement valide. Il se déchiffre correctement. Et il ne porte aucune signature — sans aucun moyen pour le destinataire de savoir qu'il y en a jamais eu une.
C'est la forme classique du downgrade : ne pas briser la cryptographie, mais simplement amener le lecteur à descendre vers un mode plus faible. C'est la même famille que le signature-stripping de TLS, et cela défait silencieusement la non-répudiation que les signatures v1.3 étaient censées fournir.
Le correctif : lier la version au texte chiffré
La v1.4 comble la faille en authentifiant les métadonnées elles-mêmes. L'en-tête sérialisé — y compris la version et les paramètres de signature — est injecté dans l'AEAD comme Additional Authenticated Data (AAD). Le tag GCM couvre désormais à la fois la charge utile et les métadonnées qui la décrivent.
AES-256-GCM(
key: fileKey,
iv: iv,
plaintext: fileBytes,
aad: canonical(metadata) ← new in v1.4
)Retournez un seul octet de l'en-tête — rétrogradez la version, supprimez la signature, échangez un nom d'algorithme — et le tag ne se vérifie plus. Le déchiffrement s'interrompt avant que le moindre texte en clair ne soit produit. Le downgrade n'est pas détecté après coup ; il est structurellement impossible à faire passer pour valide.
C'est la même défense qu'utilisent Age (HMAC sur l'en-tête), JWE (en-tête protégé comme AAD) et COSE : lier la description du texte chiffré au texte chiffré lui-même est le seul moyen de faire échouer toute altération de celle-ci.
La rétrocompatibilité, sans le piège
CVEF est versionné précisément pour cette raison. Les nouveaux fichiers sont écrits en v1.4 ; le lecteur accepte toujours v1.2, v1.3 et v1.4, afin que les coffres existants continuent de s'ouvrir. Ce qu'il ne fera pas, c'est accepter silencieusement un fichier v1.3 dont la signature a été détachée — le lien par AAD fait de la version une partie de la preuve, et non un indice que le lecteur doit croire sur parole.
Une bonne cryptographie tient rarement à un algorithme plus astucieux. Le plus souvent, elle consiste à ne laisser aucune surface non authentifiée sur laquelle un attaquant pourrait s'appuyer. La v1.4 supprime la dernière que CVEF possédait.