v0.2.5-pre.009

This commit is contained in:
2026-08-20 09:24:10 +02:00
parent 1125ade4c1
commit e91bf36e9e
83 changed files with 2467 additions and 1801 deletions

View File

@@ -1,5 +1,5 @@
<!-- file: docs/validation/000-README.md -->
<!-- version: 11 -->
<!-- version: 12 -->
# Validations KSP
@@ -17,3 +17,4 @@ Documents :
- [`006-V0_2_3_HTTP_TRANSACTIONS.md`](006-V0_2_3_HTTP_TRANSACTIONS.md) — matrice finale validée de `0.2.3`, 11 wrappers Transactions, sécurité write/simulation, réaudit 52+14, `KSP-TRANSPORT-007` 37/37, graphes Cargo et deux smokes Devnet passés avant publication stable.
- [`007-V0_2_4_HTTP_FINAL_COMPLIANCE.md`](007-V0_2_4_HTTP_FINAL_COMPLIANCE.md) — matrice finale validée de `0.2.4`, inventaire exact 52 current + 14 Deprecated, preuve typed 52/52, audit SIMD final, `KSP-TRANSPORT-007`, workspace complet et deux smokes Devnet passés avant publication stable.
- [`008-V0_2_5_WALLET_SECURITY_COMPLIANCE.md`](008-V0_2_5_WALLET_SECURITY_COMPLIANCE.md) — matrice security/interoperability/compliance de `0.2.5`, threat model V1, adversarial canaries, reproduction externe des vecteurs, audit de frontières et graphes Cargo Wallet.

View File

@@ -0,0 +1,224 @@
<!-- file: docs/validation/008-V0_2_5_WALLET_SECURITY_COMPLIANCE.md -->
<!-- version: 1 -->
# Validation `0.2.5` — Wallet security / interoperability / compliance
## 1. Objet
Cette matrice ferme le gate technique de `0.2.5-pre.009` avant la documentation finale `pre.010`. Elle ne remplace ni la spécification [`../formats/KSPWALLET_V1.md`](../formats/KSPWALLET_V1.md), ni le threat model du plan [`../plans/012-V0_2_5_WALLET_FOUNDATION_PLAN.md`](../plans/012-V0_2_5_WALLET_FOUNDATION_PLAN.md), ni les deltas.
Le verdict recherché porte sur quatre axes :
```text
security/adversarial
interoperability indépendante
frontières KSP
Cargo/dependency compliance
```
## 2. État fonctionnel audité
Au gate `pre.009`, Wallet possède :
```text
format autonome .kspwallet V1
VIEW / OWNER indépendants
Argon2id v19
XChaCha20-Poly1305
CSPRNG OS
content keys séparées OWNER / metadata / secret
Ed25519 distinct pour state_signature OWNER
keypair Solana immuable et encapsulée
create/open VIEW/OWNER
persistence no-clobber
replacement administratif capability-bound
signature Solana OWNER
alias/notes + rotations OWNER/VIEW
strong disable/recreate VIEW
import/export Solana CLI JSON + Base58 keypair 64 octets
```
Aucune dépendance Wallet vers Config, Transport, ExecutionPolicy, Store ou Tauri n'est autorisée.
## 3. Matrice adversariale
| Cas | Résultat attendu | Preuve |
|-----------------------------------------------------|---------------------------------------------------------|-----------------------------------------------------------------------------------------------|
| mutation canonique KDF/wrap OWNER | rejet | `security_tests::owner_signed_regions_reject_canonical_tampering_before_unlock` |
| mutation owner-control | rejet | même canari |
| mutation metadata | rejet | même canari |
| mutation secret | rejet | même canari |
| mutation `state_signature` | rejet | même canari |
| état OWNER-signed invalide + password vide | `wallet.authentication_failed` avant Argon2 | `security_tests::owner_signature_verification_precedes_owner_and_view_password_kdf` |
| mutation des credentials rotatables VIEW uniquement | état OWNER toujours valide, OWNER ouvrable, VIEW rejeté | `security_tests::view_credential_tampering_does_not_forge_owner_state_and_cannot_unlock_view` |
| wrong VIEW | `wallet.view_unlock_failed` générique | tests Wallet + security |
| wrong OWNER | `wallet.owner_unlock_failed` générique | tests Wallet + security |
| password canary dans Display/Debug | absent | `security_tests::unlock_failures_do_not_echo_password_material` |
| metadata plaintext dans wallet verrouillé | absent | `wallet::tests::locked_full_vector_contains_no_authorized_identity_or_metadata_plaintext` |
| stale OWNER handle | `wallet.state_conflict` | administration tests |
| wallet A handle vers wallet B | `wallet.state_conflict` | administration tests |
| écriture interrompue avant publish | ancien/destination absent préservé | persistence fault tests |
| concurrence create no-clobber | exactement un gagnant | persistence concurrency test |
| export secret depuis VIEW | surface publique absente | dependency/public-surface canary |
## 4. Ordre de vérification et anti-oracle
Pour VIEW et OWNER :
```text
parse structurel borné
-> state_signature OWNER
-> seulement ensuite Argon2 du slot demandé
-> unwrap AEAD
-> déchiffrement compartment
-> parsing plaintext protégé
```
Le canari `state_signature invalide + password vide` distingue explicitement cet ordre : si Argon2 était évalué avant l'authentification d'état, l'entrée vide produirait une erreur de paramètres crypto ; le résultat attendu reste `wallet.authentication_failed`.
Les erreurs de password ne distinguent pas KDF, wrapping AEAD ou contenu protégé et ne reflètent pas le password fourni.
## 5. Interopérabilité indépendante
Les fixtures publiques test-only restent :
```text
kspwallet_v1_wire_only.json
kspwallet_v1_crypto_vectors.json
kspwallet_v1_full_vector.json
kspwallet_v1_full_vector_meta.json
```
Une sonde indépendante hors Rust/KSP exécutée pendant `pre.009` reproduit :
```text
Argon2id OWNER derived key = exact
Argon2id VIEW derived key = exact
pre.004 XChaCha wrapped key = exact
pre.004 unwrap content key = exact
Ed25519 state signature = vérifiée sur le transcript exact
Solana keypair Base58 = reproduite depuis 64 octets
Solana Pubkey Base58 = reproduite depuis les 32 octets publics
```
La sonde utilise Python avec Argon2 et Ed25519/ChaCha20-Poly1305 disponibles localement ; XChaCha20 est reproduit par la construction HChaCha20 + ChaCha20-Poly1305 IETF. Cette sonde n'est ni versionnée ni requise par KSP : elle sert uniquement de seconde implémentation de vérification.
Références cryptographiques normatives/primaires réauditées :
- RFC 9106 — Argon2 ; le profil Argon2id `64 MiB / t=3` est la seconde recommandation pour environnements contraints ;
- RFC 8032 — Ed25519/EdDSA et signatures 64 octets ;
- documentation RustCrypto `chacha20poly1305` — XChaCha20-Poly1305 et nonce étendu 192 bits ;
- documentation `solana-keypair 3.1.2` — keypair Ed25519 64 octets, validation secret/public et codecs Base58/JSON ;
- documentation `tempfile 3.27` — publication/replacement et limites d'atomicité selon OS/filesystem.
## 6. Audit Cargo observé après `pre.008`
Commande opérateur :
```bash
cargo tree -p ksp-wallet-lib
cargo tree -p ksp-wallet-lib -d
cargo tree -i solana-keypair@3.1.2
```
Dépendances directes de Wallet observées :
```text
argon2 0.5.3
base64 0.23.1
chacha20poly1305 0.11.0
ed25519-dalek 2.2.0
getrandom 0.4.3
ksp-core-lib
ksp-logging-lib
serde 1.0.229
serde_json 1.0.151
solana-keypair 3.1.2
tempfile 3.27.0
tokio 1.53.1
zeroize 1.9.0
```
Points de convergence recherchés :
```text
ed25519-dalek 2.2.0 : une seule génération, partagée KSP + solana-keypair
solana-address 2.7.0: une seule génération, partagée solana-pubkey + solana-keypair
solana-keypair 3.1.2: unique parent KSP direct = ksp-wallet-lib
```
Doublons transitifs observés et acceptés au gate :
```text
block-buffer 0.10 / 0.12
cpufeatures 0.2 / 0.3
crypto-common 0.1 / 0.2
digest 0.10 / 0.11
getrandom 0.3 / 0.4
rand 0.9 / 0.10
rand_core 0.6 / 0.9 / 0.10
sha2 0.10 / 0.11
syn 2 / 3
```
Ces doublons proviennent des générations transitives actuelles de RustCrypto, `solana-keypair`/`solana-ed25519` et Logging. Ils ne correspondent pas à deux versions directes déclarées par Wallet pour une même fonction. Les éliminer exigerait de forcer des upstream incompatibles ou de régresser les versions retenues ; aucun contournement KSP n'est introduit.
## 7. Frontières KSP
Canaries durables :
```text
Wallet -> Core + Logging + primitives explicites
Wallet -X-> Config
Wallet -X-> Transport
Wallet -X-> ExecutionPolicy
Wallet -X-> Store
Wallet -X-> Tauri
Wallet -X-> tracing direct
Wallet -X-> std::env
Wallet -X-> solana-pubkey direct
Wallet -X-> solana-signer direct
Wallet -X-> solana-signature direct
Wallet -X-> bs58 direct
```
`ksp-core-lib::Pubkey` reste le type public transversal. `solana-keypair` reste un détail secret/signing propre à Wallet ; aucune `Keypair`, `Signer` ou `Signature` Solana externe n'est réexportée par la surface publique Wallet.
`WalletTransferFormat` est `#[non_exhaustive]` : la liste built-in reste additive et les consumers ne peuvent pas supposer qu'elle est fermée. `pre.009` ne crée pas de trait/plugin externe de codec secret : un tel trait devrait exposer les 64 octets de keypair à une implémentation tierce et constituerait une nouvelle surface secrète. Cette extension éventuelle exige un contrat dédié futur plutôt qu'une abstraction V1 prématurée.
## 8. Limites et non-garanties V1
Le verdict security est positif **dans le threat model documenté**, avec les limites explicites suivantes :
1. un remplacement total par un autre wallet autonome valide n'est pas détectable à partir du nouveau fichier seul ;
2. un rollback total vers une ancienne copie valide n'est pas détecté sans état/ancre externe ;
3. le garde-fou `wallet.state_conflict` réduit les erreurs de cible/stale handle mais n'est pas un CAS filesystem portable linéarisable ;
4. l'atomicité et la crash-durability du filesystem dépendent de l'OS/filesystem ;
5. les ACL/permissions sont une hygiène externe, pas une garantie cryptographique ;
6. `zeroize` s'applique aux buffers possédés explicitement mais ne prouve pas l'effacement physique de toutes les copies potentielles ;
7. aucune protection hardware, second facteur, keychain, remote signer ou anti-rollback externe n'est incluse en V1.
Aucune de ces limites ne doit être masquée dans `pre.010`.
## 9. Gate opérateur `pre.009`
À exécuter après application du delta :
```bash
cargo fmt --all
cargo check --workspace
cargo clippy --workspace --all-targets
cargo test -p ksp-wallet-lib
cargo test --workspace
cargo tree -p ksp-wallet-lib
cargo tree -p ksp-wallet-lib -d
cargo tree -i ed25519-dalek@2.2.0
cargo tree -i solana-keypair@3.1.2
cargo tree -i solana-address@2.7.0
```
Le gate est vert seulement si les canaris adversariaux passent sans warning et si le tree ne révèle aucune nouvelle dépendance directe ou génération Dalek/Solana-address inattendue.
## 10. Verdict avant `pre.010`
Le verdict de conception et d'interopérabilité est **positif sous réserve du checkpoint Cargo opérateur `pre.009`**. Aucun changement de wire/crypto n'est requis par l'audit. `pre.010` doit donc rester documentaire : README/USAGE Wallet, synchronisation finale de la spec/graphes, candidate de clôture et prompt `0.2.6`.