Files
khadhroony-solana-project/docs/validation/008-V0_2_5_WALLET_SECURITY_COMPLIANCE.md
2026-08-20 12:31:08 +02:00

16 KiB
Raw Permalink Blame History

Validation 0.2.5 — Wallet security / interoperability / compliance

1. Objet

Cette matrice constitue la validation durable de clôture de la release stable 0.2.5. pre.009 a fermé le premier gate technique security/interoperability/compliance, pre.010 le gate documentaire, puis pre.010-fix.001fix.003 ont fermé la mise à niveau ed25519-dalek 3.0.0, la normalisation Rust workspace-wide et la compatibilité entre rustfmt et laudit Python avant publication. Elle ne remplace ni la spécification ../formats/KSPWALLET_V1.md, ni le threat model du plan ../plans/012-V0_2_5_WALLET_FOUNDATION_PLAN.md, ni les deltas.

Le verdict recherché porte sur quatre axes :

security/adversarial
interoperability indépendante
frontières KSP
Cargo/dependency compliance

2. État fonctionnel audité

Au gate pre.009, Wallet possède :

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 :

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 :

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 :

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 final observé après pre.009

Commande opérateur :

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 :

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 :

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 :

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 :

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.

pre.010 les conserve explicitement dans README/USAGE/spec et ne les transforme pas en garanties.

9. Gate opérateur pre.009

À exécuter après application du delta :

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

Ce gate est considéré vert uniquement 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 ; le résultat effectivement observé est enregistré en section 10.

10. Résultat opérateur pre.009

Checkpoint communiqué le 2026-08-19 après application de 0.2.5-pre.009 :

cargo fmt --all                         OK
cargo check --workspace                 OK, aucun warning
cargo clippy --workspace --all-targets  OK, aucun warning
cargo test -p ksp-wallet-lib            OK
  unit                                  58 passed / 1 ignored
  dependency_boundary                    3 passed
  public_api                             9 passed
  doctests                               2 passed
cargo test --workspace                  OK

Le tree opérateur confirme :

ed25519-dalek 2.2.0
  <- ksp-wallet-lib
  <- solana-keypair 3.1.2 <- ksp-wallet-lib

solana-keypair 3.1.2
  <- ksp-wallet-lib uniquement comme parent KSP direct

solana-address 2.7.0
  <- solana-keypair 3.1.2
  <- solana-pubkey 4.3.0 via ksp-core-lib

Les doublons transitifs déjà inventoriés restent inchangés et aucun nouveau bypass de frontière n'est observé.

11. Gate documentaire pre.010

La candidate finale doit vérifier :

crates/ksp-wallet-lib/README.md existe et décrit les responsabilités/frontières
crates/ksp-wallet-lib/USAGE.md couvre create/open/sign/admin/rotation/import/export
KSPWALLET_V1.md ne laisse aucune opération V1 planifiée comme restant à implémenter
le graphe Wallet documente Pubkey via Core et keypair encapsulée dans Wallet
le plan 0.2.5 pointe désormais vers rel.001
le prompt 0.2.6 Wallet Desk existe et commence par audit/sizing
les liens Markdown locaux modifiés sont valides
aucun fichier Rust ni manifest Cargo n'est modifié par pre.010
workspace.package.version reste 0.2.5-pre.9 car pre.010 est doc-only

12. Correctifs de clôture pre.010-fix.001 à fix.003

La clôture technique apporte :

ed25519-dalek direct KSP : ^2.2 -> ^3.0
normalisation Rust workspace-wide
scripts/audit_rust_workspace_rules.py obligatoire après cargo fmt
corrections des chemins crate::/super:: et des réexports crate-root
espacement structurel normalisé
audit Python rendu compatible avec l'ordre canonique produit par rustfmt
prompt 0.2.6 renforcé + TODO 0.2.11 prix offchain dans Wallet Desk

Le wire .kspwallet V1, les paramètres Argon2/XChaCha, la sémantique Ed25519, les capabilities VIEW/OWNER et les API Wallet fonctionnelles ne changent pas pendant ces fixes.

Le tree final attendu et observé contient deux générations Dalek intentionnelles :

ed25519-dalek 3.0.0
  <- ksp-wallet-lib direct

ed25519-dalek 2.2.0
  <- solana-keypair 3.1.2
  <- ksp-wallet-lib

solana-address 2.7.0
  <- solana-keypair 3.1.2
  <- solana-pubkey 4.3.0 via ksp-core-lib

La génération 2.2.0 n'est pas un doublon direct KSP à corriger artificiellement : elle reste imposée par solana-keypair 3.1.2.

13. Checkpoint opérateur final pre.010-fix.003

Validation communiquée le 20 août 2026 :

cargo fmt --all                         OK
python3 scripts/audit_rust_workspace_rules.py
  General Rust rule audit               clean
  Rust export completeness audit        0 candidate(s)
  KSP workspace Rust rule audit         clean
cargo check --workspace                 OK
cargo clippy --workspace --all-targets  OK
cargo test -p ksp-wallet-lib            OK
  unit                                  58 passed / 1 ignored
  dependency_boundary                    3 passed
  public_api                             9 passed
  doctests                               2 passed
cargo test --workspace                  OK

Le checkpoint ne rapporte aucun warning Clippy ou compilation. Les tests Config Desk, Config, Core, Logging, Transport et Wallet passent dans le workspace complet ; les smokes réseau opt-in restent volontairement ignored dans la suite déterministe.

14. Audit Cargo final

Le dernier audit de dépendances avant release confirme notamment :

ed25519-dalek 3.0.0
  <- ksp-wallet-lib

ed25519-dalek 2.2.0
  <- solana-keypair 3.1.2 <- ksp-wallet-lib

solana-keypair 3.1.2
  <- ksp-wallet-lib uniquement comme parent KSP direct

solana-address 2.7.0
  <- solana-keypair 3.1.2
  <- solana-pubkey 4.3.0 via ksp-core-lib

Les doublons transitifs RustCrypto/Solana déjà documentés restent acceptés et n'introduisent aucun second owner KSP du secret Solana.

15. Verdict final 0.2.5

Verdict positif. Tous les gates déterministes et structurels requis avant publication sont verts sur 0.2.5-pre.010-fix.003.

0.2.5-rel.001 est donc strictement publicationnelle :

workspace.package.version -> 0.2.5
aucun changement Rust fonctionnel
aucun changement du wire .kspwallet V1
aucune nouvelle dépendance/feature
CHANGELOG/ROADMAP/plans/validation synchronisés
commit attendu : v0.2.5-rel.001
tag stable attendu : v0.2.5

Après validation du delta rel.001, la session suivante s'ouvre avec prompts/011-V0_2_6_START_PROMPT.md et commence par 0.2.6-pre.001 audit/sizing.