Files
khadhroony-bot3/docs/guides/WALLETS.md
2026-08-11 15:15:03 +02:00

12 KiB

Wallets, sécurité et opérations

1. Objet

Ce guide décrit le contrat opérationnel de ks-wallet à partir de 0.5.2.

ks-wallet possède :

  • le stockage local des wallets Solana persistants ;
  • la protection par mot de passe ;
  • l'ouverture authentifiée ;
  • la capacité de signature ;
  • les imports/exports de formats secrets explicitement supportés.

Il ne possède pas :

  • la politique d'autorisation d'une transaction ;
  • les plafonds de dépense ;
  • le routage RPC ;
  • la classification on-chain d'une pubkey ;
  • les DTO frontend d'une application Tauri.

2. Modèle de données

2.1 Identité publique

Une identité publique contient uniquement :

  • alias ;
  • pubkey ;
  • persistance temporaire ou persistante.

Une identité publique ne contient jamais le secret, le mot de passe, le ciphertext ou un chemin local.

2.2 Wallet temporaire

TemporaryWallet::generate() crée un keypair en mémoire. Il ne nécessite ni mot de passe ni fichier.

Cette surface reste adaptée aux tests synthétiques et signers jetables. Les fixtures/keypairs persistées uniquement pour les campagnes historiques restent sous wallets/temporary/**; elles ne doivent pas être confondues avec les .kswallet persistants de wallets/.

2.3 Wallet persistant

Le format natif est :

<alias>.kswallet

Le layout exact est défini dans ../NATIVE_FORMAT.md.

Le store automatique de WalletManager :

  • scanne uniquement son répertoire configuré ;
  • ne descend pas récursivement ;
  • ignore les extensions étrangères ;
  • refuse symlinks et fichiers non réguliers ;
  • exige des permissions privées sous Unix ;
  • valide le conteneur complet avant de retourner un handle.

3. Protection cryptographique

Le format v1 utilise :

Élément Contrat v1
KDF Argon2id v19
Profil d'écriture 64 MiB, 3 passes, 4 lanes
Sel 16 octets
Clé dérivée 32 octets
AEAD XChaCha20-Poly1305
Nonce 24 octets
Plaintext keypair Solana exacte de 64 octets
Ciphertext + tag 80 octets
AAD header + alias + sel + nonce

Les paramètres lus sont bornés avant l'exécution du KDF.

La pubkey présente dans le header n'est pas considérée comme authentifiée avant l'unlock. Après déchiffrement, ks-wallet reconstruit le keypair et vérifie que sa pubkey correspond exactement au header avant de produire une capacité de signature.

4. Mot de passe et cycle de vie

WalletPassword :

  • prend possession de sa chaîne ;
  • n'est pas clonable ;
  • n'est pas sérialisable ;
  • possède un Debug redacted ;
  • zéroïse la valeur qu'il possède à la destruction.

WalletManager::create() crée un wallet natif et retourne UnlockedWallet.

WalletManager::unlock() ouvre un wallet du store par alias.

WalletManager::unlock_file() ouvre un WalletFileHandle obtenu par inspection explicite d'un fichier externe.

UnlockedWallet :

  • possède le keypair authentifié ;
  • n'est pas clonable ;
  • expose Signer / Signer + Sync ;
  • n'expose pas les 64 octets privés ;
  • est verrouillé par consommation explicite avec lock() ou par fin de portée.

Un changement de mot de passe ne change pas la keypair. Il produit un nouveau sel et un nouveau nonce, puis reprotège exactement la même identité Solana.

Une UnlockedWallet déjà remise à un consommateur n'est pas révoquée rétroactivement par un changement de mot de passe. Son propriétaire doit la détruire ou appeler lock().

5. Écriture et permissions

Les nouveaux .kswallet sont publiés sans écrasement silencieux.

Sous Unix :

  • répertoire wallet : 0700 ;
  • fichier .kswallet : 0600 ;
  • exports secrets : 0600.

Les écritures natives utilisent un fichier temporaire privé dans le même répertoire, sync_all, puis une publication atomique/no-clobber. Le changement de mot de passe remplace le fichier après authentification de l'ancien secret.

Les collisions concurrentes de création d'un même alias doivent produire exactement un gagnant et conserver une destination native valide.

6. Configuration

wallet.config.json contient une racine globale wallets_directory et des profils.

Un profil peut sélectionner :

{
  "wallet_alias": "operator"
}

ou laisser :

{
  "wallet_alias": null
}

L'alias est une sélection non sensible. Aucun mot de passe n'est stocké dans ks-config.

Lorsqu'un alias persistant est configuré, un consommateur ne doit pas retomber silencieusement sur un wallet temporaire : il doit acquérir explicitement le mot de passe et appeler l'API d'unlock.

7. Migration legacy

Le legacy historique est :

<alias>.json

avec le tableau JSON des 64 octets du keypair Solana.

WalletManager::migrate_legacy() :

  1. lit la source legacy privée ;
  2. valide le keypair ;
  3. crée <alias>.kswallet ;
  4. vérifie que la pubkey est identique ;
  5. conserve la source JSON intacte.

La suppression du legacy reste une décision explicite de l'opérateur après validation.

TemporaryWalletStore reste disponible pour les scénarios historiques. Ses erreurs, logs et Debug ne doivent pas projeter les chemins locaux, même si ses getters explicites directory() et wallet_path() restent nécessaires aux outils de fixtures.

8. Import et export

Les formats secrets actuellement supportés sont :

Format Import Export Mot de passe requis à l'export
WalletTransferFormat::SolanaCliJson oui oui oui
WalletTransferFormat::SolanaPrivateKeyBase58 oui oui oui

La matrice détaillée est dans ../WALLET_FORMAT_COMPATIBILITY.md.

L'import refuse :

  • source non régulière ou symlink ;
  • permissions trop ouvertes sous Unix ;
  • format invalide ;
  • keypair de taille incorrecte ;
  • alias déjà occupé ;
  • pubkey déjà gérée sous un autre alias natif.

L'export authentifie d'abord le .kswallet, puis seulement après crée la destination. Il n'écrase jamais silencieusement un fichier existant.

9. Keypair, wallet, mint et authority

Une keypair Solana ne contient pas son rôle métier.

Le même type de secret Ed25519 peut servir comme :

  • payer/opérateur ;
  • mint authority ;
  • freeze authority ;
  • clé utilisée lors de la création d'un mint ;
  • recipient possédant lui-même un signer ;
  • autre authority ou signer de fixture.

Il est donc incorrect de décider « ce fichier est un mint et non un wallet » uniquement à partir du tableau JSON de 64 octets.

La future inspection de wallets/temporary/** prévue avec 0.5.4 doit produire un inventaire local factuel :

format détecté
keypair valide / invalide / format non supporté
pubkey si valide

Un consommateur peut ensuite interroger un réseau donné avec cette pubkey et classifier l'état actuel de l'adresse, par exemple :

  • compte absent ;
  • compte système ;
  • mint SPL Token ;
  • mint Token-2022 ;
  • compte token ;
  • programme ou autre compte.

Cette classification reste réseau-dépendante et ne prouve pas tous les rôles historiques du signer.

ks-wallet ne doit pas dépendre de ks-onchain-transport pour réaliser cette classification.

10. Desktop de démonstration

kb-app-demo-desktop possède ses propres DTO Tauri et ne sérialise pas les types secrets de ks-wallet.

La fenêtre Wallets permet :

  • inventaire des .kswallet de wallets/ ;
  • création d'un wallet natif avec un secret backend-only ;
  • inspection d'un .kswallet externe ;
  • inspection/import d'un keypair Solana CLI JSON ou Base58 sans exposer son secret au frontend ;
  • export secret authentifié vers data/wallets/ avec nom de fichier borné et sans chemin arbitraire côté frontend ;
  • sélection explicite d'un profil RPC pour les lectures publiques ;
  • consultation du solde SOL, des comptes SPL Token/Token-2022, des signatures récentes et du détail getTransaction ;
  • sélection session-only du .kswallet utilisé par les démos Devnet.

Le mot de passe de démonstration est lu uniquement côté backend depuis :

KB_SECRET_DEMO_WALLET_PASSWORD

La sélection runtime du wallet d'exécution est authentifiée avant activation et ne réécrit pas wallet.config.json. L'ordre de résolution est :

override session demo_wallet
    -> wallet_alias du profil
    -> wallet temporaire uniquement si aucun alias persistant n'est sélectionné

Lorsqu'un alias persistant est effectif, les adaptateurs Devnet System/SPL/Metadata utilisent une capacité UnlockedWallet et ne retombent pas silencieusement sur le JSON temporaire. La validation opérateur 0.5.2 a observé persistence="persistent" avec la pubkey sélectionnée.

Le profil RPC choisi dans la fenêtre Wallets ne modifie ni le profil actif global ni le store wallet actif ; il borne uniquement les lectures on-chain de cette fenêtre.

10.1 Répertoires opérateur

La convention du desktop est :

wallets/
  <alias>.kswallet
  temporary/<profil>/...

data/wallets/
  <exports secrets explicites>

wallets/ est la racine persistante native. wallets/temporary/** appartient aux fixtures/keypairs historiques. data/wallets/ contient les exports explicites destinés à des outils externes et ne doit pas être rescanné automatiquement comme store natif.

10.2 Validation du changement de mot de passe

Le changement de mot de passe n'est volontairement pas exposé dans le frontend. La crate ks-wallet-demo-scenarios valide ce cycle comme consommateur externe de l'API publique :

A -> B
A rejeté
B ouvre et signe
B -> A
A ouvre et signe

Le test utilise un .kswallet synthétique dans un répertoire temporaire privé et ne modifie aucun wallet réel de l'opérateur.

11. Non-divulgation

Ne jamais placer un secret wallet dans :

  • wallet.config.json ;
  • KS_PUBLIC_* ou KB_PUBLIC_* ;
  • un payload Tauri ;
  • un DTO TS-RS généraliste ;
  • un log ;
  • un message d'erreur normal ;
  • un Debug automatique d'un type sensible.

Les chemins locaux ne sont pas des secrets cryptographiques, mais ils restent des informations internes et ne doivent pas apparaître inutilement dans les logs, erreurs et DTO fonctionnels.

12. Modèle de menace borné

0.5.2 protège le secret persistant contre la lecture directe du fichier sans mot de passe et impose des permissions privées ainsi qu'un chiffrement authentifié.

Cette version ne prétend pas protéger contre :

  • une machine déjà compromise pendant qu'un wallet est déverrouillé ;
  • un processus disposant des mêmes droits utilisateur et capable de lire la mémoire ;
  • la saisie volontaire du mot de passe dans un programme malveillant ;
  • la copie volontaire d'un .kswallet et de son mot de passe vers une autre installation compatible ;
  • hardware wallet, Ledger, KMS ou HSM.

13. Références