215 lines
8.9 KiB
Markdown
215 lines
8.9 KiB
Markdown
<!-- file: crates/ksp-wallet-lib/README.md -->
|
|
<!-- version: 4 -->
|
|
|
|
# `ksp-wallet-lib`
|
|
|
|
Statut : **stable depuis KSP `0.2.5`**.
|
|
|
|
`ksp-wallet-lib` est la bibliothèque KSP propriétaire du Wallet Solana natif. Elle possède le format autonome `.kspwallet` V1 et le format binaire V2 canonique, les capacités indépendantes VIEW/OWNER, la protection du secret Solana, la signature, l'administration des metadata, les rotations de credentials, la persistence native et les adapters d'import/export explicitement supportés. Depuis `0.2.6-pre.016`, les APIs non versionnées créent/importent en V2 par default explicite et lisent V1/V2 par détection bornée.
|
|
|
|
La crate est volontairement indépendante de Config, du réseau et de Tauri. Un consumer fournit les chemins, passwords et metadata ; Wallet ouvre, protège, signe et persiste sans décider d'une policy de dépense ni contacter un RPC.
|
|
|
|
## Responsabilités
|
|
|
|
La crate possède :
|
|
|
|
- le format natif `.kspwallet` V1 et son parser JSON strict ;
|
|
- le wire binaire `.kspwallet` V2, son codec borné/canonique, sa création/ouverture/persistence et ses domains/transcripts distincts ;
|
|
- la façade générique V1/V2 et les variantes `_v1`/`_v2` permettant soit le default, soit un wire forcé ;
|
|
- les key slots OWNER/VIEW indépendants ;
|
|
- Argon2id pour les KDF de passwords ;
|
|
- XChaCha20-Poly1305 pour le wrapping et les compartiments ;
|
|
- une autorité Ed25519 d'administration distincte de la keypair Solana ;
|
|
- les compartiments `owner_control`, `metadata` et `secret` ;
|
|
- la création et l'ouverture in-memory ;
|
|
- la création et l'ouverture fichier async-first ;
|
|
- la projection verrouillée minimale ;
|
|
- la signature Solana via OWNER sans getter secret ;
|
|
- l'alias et les notes protégés ;
|
|
- les rotations OWNER/VIEW ;
|
|
- la révocation forte VIEW par OWNER ;
|
|
- la persistence create/import no-clobber ;
|
|
- le remplacement administratif capability-bound avec détection de handle stale ;
|
|
- l'inspection/import/export Solana CLI JSON et Base58 de keypair complète ;
|
|
- les diagnostics et erreurs Wallet sans exposition de secrets.
|
|
|
|
La crate ne possède pas :
|
|
|
|
```text
|
|
Config
|
|
Transport HTTP/WebSocket/gRPC
|
|
balance/réseau
|
|
WalletPolicy / execution policy
|
|
construction ou envoi de transaction
|
|
Store
|
|
Tauri/UI
|
|
hardware wallet / remote signer
|
|
anti-rollback externe
|
|
```
|
|
|
|
## Frontières de dépendances
|
|
|
|
La direction de production est :
|
|
|
|
```text
|
|
ksp-wallet-lib
|
|
-> ksp-core-lib
|
|
-> ksp-logging-lib
|
|
-> argon2 / chacha20poly1305 / getrandom
|
|
-> ed25519-dalek / solana-keypair
|
|
-> serde / serde_json
|
|
-> tempfile / tokio
|
|
-> zeroize
|
|
```
|
|
|
|
Les dépendances suivantes sont interdites :
|
|
|
|
```text
|
|
ksp-wallet-lib -X-> ksp-config-lib
|
|
ksp-wallet-lib -X-> ksp-onchain-transport-lib
|
|
ksp-wallet-lib -X-> execution policy
|
|
ksp-wallet-lib -X-> Store
|
|
ksp-wallet-lib -X-> Tauri
|
|
ksp-wallet-lib -X-> tracing direct
|
|
ksp-wallet-lib -X-> std::env
|
|
ksp-wallet-lib -X-> solana-pubkey direct
|
|
ksp-wallet-lib -X-> solana-signer direct
|
|
ksp-wallet-lib -X-> solana-signature direct
|
|
```
|
|
|
|
La Pubkey publique est toujours `ksp_core_lib::Pubkey`. `solana-keypair` reste un détail secret/signing interne à Wallet et n'est pas réexportée.
|
|
|
|
## Modèle de capacités
|
|
|
|
### Verrouillé
|
|
|
|
Sans password, `inspect_locked_wallet_v1` et `inspect_locked_wallet_file_v1` exposent uniquement :
|
|
|
|
```text
|
|
format_version
|
|
view_enabled
|
|
```
|
|
|
|
La Pubkey, l'alias et les notes restent chiffrés.
|
|
|
|
### VIEW
|
|
|
|
`WalletView` expose :
|
|
|
|
```text
|
|
Pubkey
|
|
alias
|
|
notes
|
|
rotation de son propre password VIEW
|
|
```
|
|
|
|
VIEW ne possède aucune API de signature, d'export secret, de mutation metadata, de rotation OWNER ou de désactivation/recréation VIEW.
|
|
|
|
### OWNER
|
|
|
|
`WalletOwner` expose toutes les metadata autorisées et ajoute :
|
|
|
|
```text
|
|
signature Solana
|
|
export du secret via adapters explicites
|
|
alias/notes administration
|
|
rotation OWNER
|
|
rotation VIEW sans ancien password VIEW
|
|
disable VIEW avec rekey metadata fort
|
|
recreate VIEW avec nouveau slot et nouveau K_metadata
|
|
```
|
|
|
|
OWNER ne dépend jamais du password VIEW.
|
|
|
|
## Format `.kspwallet` V1
|
|
|
|
Le format est publiquement spécifié dans [`../../docs/formats/KSPWALLET_V1.md`](../../docs/formats/KSPWALLET_V1.md). Il est autonome : un fichier valide et le password de la capacité concernée suffisent à l'ouverture ; aucun pepper KSP, keychain, OTP, service distant, réseau ou secret externe n'est requis.
|
|
|
|
Les principales primitives sont :
|
|
|
|
```text
|
|
KDF Argon2id v19
|
|
profil création 65 536 KiB / 3 iterations / 1 lane
|
|
AEAD XChaCha20-Poly1305
|
|
CSPRNG OS via getrandom
|
|
state signature Ed25519
|
|
wire binary Base64url sans padding
|
|
format JSON UTF-8 strict
|
|
```
|
|
|
|
Les paramètres KDF sont sérialisés dans chaque slot afin que de futurs defaults puissent évoluer sans rendre les wallets existants illisibles.
|
|
|
|
## Persistence
|
|
|
|
Toute création/import reçoit un chemin explicite du caller et applique le no-clobber. Wallet ne découvre ni ne crée un répertoire configuré par lui-même.
|
|
|
|
Les mutations OWNER/VIEW persistées utilisent un remplacement capability-bound : le fichier courant doit encore correspondre à l'enveloppe authentifiée attendue par le handle. Un handle stale ou une mauvaise cible retourne `wallet.state_conflict`.
|
|
|
|
Cette protection ne constitue pas un CAS filesystem linéarisable et ne fournit pas d'anti-rollback externe. Les garanties d'atomicité/crash-durability dépendent également de l'OS et du filesystem.
|
|
|
|
## Import/export
|
|
|
|
Les formats built-in V1 sont :
|
|
|
|
```text
|
|
WalletTransferFormat::SolanaCliJson
|
|
WalletTransferFormat::SolanaKeypairBase58
|
|
```
|
|
|
|
L'inspection d'un transfert retourne seulement sa Pubkey et son format. L'import crée toujours un nouveau `.kspwallet` no-clobber autour de la keypair validée. L'export secret appartient uniquement à `WalletOwner`.
|
|
|
|
`WalletTransferFormat` est `#[non_exhaustive]` afin de permettre des formats built-in supplémentaires sans prétendre fournir un plugin public arbitraire de codec secret.
|
|
|
|
## Sécurité et limites
|
|
|
|
Le threat model V1 considère notamment un attaquant possédant une copie complète du fichier et capable d'essais de password offline sans limite serveur. Argon2id augmente le coût de chaque essai ; il ne compense pas un password faible.
|
|
|
|
Limites explicitement assumées :
|
|
|
|
- remplacement total par un autre wallet valide non détectable depuis le nouveau fichier seul ;
|
|
- rollback vers une ancienne copie valide non détectable sans état/ancre externe ;
|
|
- absence de second facteur, keychain, hardware wallet ou remote signer en V1 ;
|
|
- `zeroize` réduit les copies possédées mais ne prouve pas l'effacement physique de toute copie potentielle ;
|
|
- les permissions filesystem sont une hygiène externe, pas une garantie cryptographique.
|
|
|
|
La matrice durable [`../../docs/validation/008-V0_2_5_WALLET_SECURITY_COMPLIANCE.md`](../../docs/validation/008-V0_2_5_WALLET_SECURITY_COMPLIANCE.md) enregistre les canaris adversariaux, l'interop indépendante et l'audit Cargo.
|
|
|
|
## Tests et vecteurs
|
|
|
|
Les fixtures publiques test-only sont sous `tests/fixtures/` :
|
|
|
|
```text
|
|
kspwallet_v1_wire_only.json
|
|
kspwallet_v1_crypto_vectors.json
|
|
kspwallet_v1_full_vector.json
|
|
kspwallet_v1_full_vector_meta.json
|
|
```
|
|
|
|
Elles couvrent le wire, Argon2id/XChaCha20-Poly1305, l'ouverture VIEW/OWNER, la signature d'état et l'interop transfer. Les tests adversariaux couvrent tampering, wrong passwords, frontières VIEW/OWNER, persistence, concurrence et diagnostics secrets.
|
|
|
|
## Documentation
|
|
|
|
- [`USAGE.md`](USAGE.md) — exemples des principales surfaces publiques ;
|
|
- [`../../docs/formats/KSPWALLET_V1.md`](../../docs/formats/KSPWALLET_V1.md) — spécification normative indépendante de Rust ;
|
|
- [`../../docs/plans/012-V0_2_5_WALLET_FOUNDATION_PLAN.md`](../../docs/plans/012-V0_2_5_WALLET_FOUNDATION_PLAN.md) — plan historique et threat model de `0.2.5` ;
|
|
- [`../../docs/validation/008-V0_2_5_WALLET_SECURITY_COMPLIANCE.md`](../../docs/validation/008-V0_2_5_WALLET_SECURITY_COMPLIANCE.md) — matrice de sécurité/interoperabilité/compliance ;
|
|
- [`../../prompts/011-V0_2_6_START_PROMPT.md`](../../prompts/011-V0_2_6_START_PROMPT.md) — reprise vers Wallet Desk après publication stable de `0.2.5`.
|
|
|
|
## V2 en `0.2.6-pre.015` / `pre.016`
|
|
|
|
`pre.015` a figé le wire structurel V2, son codec et ses transcripts/AAD. `pre.016` matérialise le runtime V2 complet et la façade multi-version :
|
|
|
|
```text
|
|
DEFAULT_WALLET_FORMAT = V2
|
|
LATEST_SUPPORTED_WALLET_FORMAT = V2
|
|
|
|
create_wallet_file(...) -> V2
|
|
create_wallet_file_v1(...) -> V1 forcé
|
|
create_wallet_file_v2(...) -> V2 forcé
|
|
|
|
open/inspect génériques -> détection V1/V2
|
|
open/inspect _v1/_v2 -> format forcé strict
|
|
```
|
|
|
|
`WalletOwner` et `WalletView` conservent le format natif qu'ils ont ouvert : metadata, rotations OWNER/VIEW, disable/recreate VIEW, self-rotation VIEW, signature et export ne transcodent jamais implicitement le fichier. Le default est une décision explicite et ne suit pas automatiquement une future V3. La migration authentifiée V1 -> V2 reste une opération séparée de `pre.017`.
|