v0.2.5-pre.001-fix.001
This commit is contained in:
@@ -1,5 +1,5 @@
|
||||
<!-- file: docs/plans/012-V0_2_5_WALLET_FOUNDATION_PLAN.md -->
|
||||
<!-- version: 2 -->
|
||||
<!-- version: 4 -->
|
||||
|
||||
# Plan `0.2.5` — Wallet foundation
|
||||
|
||||
@@ -72,14 +72,18 @@ Clarifications confirmées pendant la revue du gate :
|
||||
|
||||
23. **`.kspwallet` V1 est entièrement autonome** : le fichier et le password correspondant sont les seuls éléments requis pour parser, vérifier l'intégrité sous son autorité OWNER embarquée, déverrouiller et récupérer les capacités prévues. V1 n'utilise et ne requiert aucun salt externe, pepper KSP, OTP, secret serveur, keychain, état machine, réseau ou ancre de confiance externe ;
|
||||
24. la spécification finale est un document séparé `docs/formats/KSPWALLET_V1.md`, indépendant de l'implémentation Rust et suffisamment précis pour réimplémenter le format dans un autre langage sans lire `ksp-wallet-lib` ;
|
||||
25. toute mutation persistante acceptée sous l'autorité d'un wallet V1 est **OWNER-authorized** : key slots, paramètres KDF, compartments, metadata et état de protection sont couverts par l'authentification OWNER ; VIEW reste incapable de forger un nouvel état valide sous cette même autorité ;
|
||||
26. la keypair Solana est **immuable dans un wallet V1 après création/import**. V1 ne fournit pas d'opération de remplacement de keypair ; une autre keypair crée un autre wallet.
|
||||
25. l'état **OWNER-controlled** d'un wallet V1 est authentifié par OWNER : identité Solana, metadata, secret, slot OWNER, activation/désactivation de VIEW, descripteur stable du slot VIEW et paramètres de format concernés ne peuvent pas être modifiés sous l'autorité courante sans OWNER ;
|
||||
26. **VIEW peut modifier une seule chose : son propre password VIEW**. Cette opération remplace uniquement les paramètres KDF VIEW autorisés par V1, le salt et le nonce/ciphertext de wrapping de son slot en rewrappant le même accès metadata ; elle ne donne aucun droit d'écriture sur Pubkey/alias/notes, aucun droit de signature/export, aucun droit de changer OWNER et aucun droit de désactiver/recréer VIEW ;
|
||||
27. **OWNER peut changer son propre password OWNER et le password VIEW**, sans connaître l'ancien password VIEW ; OWNER reste seul capable de l'administration metadata et des key slots au-delà du self-service de rotation VIEW ;
|
||||
28. la keypair Solana est **immuable dans un wallet V1 après création/import**. V1 ne fournit pas d'opération de remplacement de keypair ; une autre keypair crée un autre wallet ;
|
||||
29. les permissions/ACL du système de fichiers ne constituent **ni une garantie cryptographique ni une responsabilité de sécurité de `ksp-wallet-lib`**. Le contrat Wallet porte sur les capacités : sans OWNER, aucune signature Solana, aucun export secret, aucune écriture acceptée de Pubkey/alias/notes et aucune mutation OWNER-controlled ; la seule mutation volontairement accordée à VIEW est la rotation de son propre password ;
|
||||
30. tout import produit un **nouveau `.kspwallet`** selon la sémantique no-clobber de `create`. Un import ne remplace, n'écrase et ne transforme jamais un `.kspwallet` existant.
|
||||
|
||||
## 4. Réaudit de l'héritage bot2/bot3
|
||||
|
||||
### 4.1 bot2 — `TemporaryWalletStore`
|
||||
|
||||
L'archive historique contient un store de laboratoire basé sur le keypair JSON Solana 64 octets. Les propriétés utiles sont : validation stricte du keypair, no-clobber, permissions Unix `0700/0600`, effacement des buffers sérialisés et frontière `Signer` sans exposition publique des octets privés.
|
||||
L'archive historique contient un store de laboratoire basé sur le keypair JSON Solana 64 octets. Les propriétés utiles sont : validation stricte du keypair, no-clobber, effacement des buffers sérialisés et frontière `Signer` sans exposition publique des octets privés. Les permissions Unix `0700/0600` observées historiquement ne sont pas reprises comme garantie de sécurité Wallet : les ACL/permissions OS restent hors du threat model de `.kspwallet` V1.
|
||||
|
||||
Le format lui-même est **abandonné** pour KSP natif : il n'offre aucun chiffrement password et le prompt `0.2.5` exclut explicitement sa migration.
|
||||
|
||||
@@ -178,7 +182,7 @@ Solana secret/keypair
|
||||
format-admin signing secret
|
||||
```
|
||||
|
||||
L'API KSP VIEW ne conserve pas la metadata content key après déchiffrement ; elle expose une projection read-only et ne possède aucune méthode de signature ou d'administration.
|
||||
L'API KSP VIEW expose une projection metadata read-only et ne possède aucune méthode de signature, d'export secret ni d'administration metadata/OWNER. Elle peut toutefois conserver, pour la durée de vie explicitement contrôlée de la capability déverrouillée, le **minimum de matériau VIEW** nécessaire à la lecture et au rewrap de son propre slot ; ce matériau est privé, zeroized au drop lorsque raisonnablement possible et ne contient jamais le secret Solana ni une clé OWNER.
|
||||
|
||||
### 5.4 OWNER compromis
|
||||
|
||||
@@ -188,52 +192,53 @@ Une future opération de rekey cryptographique complet pourrait changer l'owner
|
||||
|
||||
### 5.5 Modification partielle du fichier
|
||||
|
||||
Les ciphertexts sont authentifiés par AEAD et l'état global accepté est couvert par l'authentification OWNER définie plus bas. Toute modification partielle d'un champ couvert doit provoquer un rejet déterministe sans exposer une cause crypto trop fine.
|
||||
Les ciphertexts sont authentifiés par AEAD. L'état OWNER-controlled est couvert par l'authentification OWNER définie plus bas ; les champs self-service du slot VIEW sont couverts par leur wrapping AEAD et leur binding AAD. Toute modification partielle d'un champ hors contrat doit provoquer un rejet déterministe sans exposer une cause crypto trop fine.
|
||||
|
||||
### 5.6 Remplacement total / rollback
|
||||
|
||||
Un attaquant capable de remplacer le fichier entier peut substituer :
|
||||
Un remplacement intégral par un autre `.kspwallet` valide ne révèle **aucun** matériau secret de l'ancien wallet : il revient seulement à substituer un autre wallet, avec sa propre autorité OWNER, ses propres key slots et sa propre keypair Solana. Si l'attaquant ne connaît pas VIEW de l'ancien wallet, cette substitution ne lui donne pas davantage accès à la Pubkey/alias/notes de l'ancien fichier.
|
||||
|
||||
```text
|
||||
owner auth public key
|
||||
key slots
|
||||
ciphertexts
|
||||
state signature
|
||||
```
|
||||
Un format V1 entièrement autonome ne peut pas distinguer, à partir du seul nouveau fichier, qu'une autre autorité OWNER a remplacé l'ancienne. La même limite vaut pour un rollback complet vers une ancienne copie valide. Ce point n'est **pas** une garantie recherchée par `ksp-wallet-lib` V1 et n'autorise aucune dépendance externe : aucun salt externe, pepper, OTP, secret KSP, service distant, keychain ou ancre de confiance extérieure n'est requis.
|
||||
|
||||
par ceux d'un autre wallet valide. Un format autonome ne peut pas détecter cette substitution à partir d'une information de confiance stockée uniquement dans le fichier substitué.
|
||||
|
||||
La même limite vaut pour un rollback complet vers une ancienne copie valide. Cette limite n'autorise **aucune dépendance externe en V1** : le format V1 reste volontairement auto-contenu et interdit comme prérequis tout salt externe, pepper, OTP, secret KSP, service distant, keychain ou ancre de confiance extérieure. Une éventuelle version de format future pourrait étudier un facteur/ancrage externe, mais ce mécanisme n'appartient ni au format V1 ni à `0.2.5`.
|
||||
Les permissions/ACL et le contrôle de qui peut écrire le chemin relèvent du système d'exploitation et sont hors du threat model Wallet. Le contrat V1 porte sur les capacités : **sans OWNER**, aucun détenteur ne peut signer avec la keypair Solana, exporter son secret, modifier Pubkey/alias/notes ni muter l'état OWNER-controlled. Un détenteur VIEW authentifié conserve uniquement l'exception explicitement accordée de rotation de son propre password VIEW.
|
||||
|
||||
### 5.7 Matrice des garanties
|
||||
|
||||
| Garantie | Cryptographie fichier | Types/capabilities KSP | Filesystem | Ancre externe éventuelle, hors V1 |
|
||||
|-------------------------------------------------------------------|----------------------:|-----------------------:|----------------------:|----------------------------------------------------------:|
|
||||
| confidentialité metadata verrouillées | oui | oui | complément | non |
|
||||
| confidentialité secret Solana face à VIEW | oui | oui | complément | non |
|
||||
| indépendance VIEW/OWNER | oui | oui | non | non |
|
||||
| VIEW ne signe pas | séparation de clés | oui | non | non |
|
||||
| VIEW ne modifie pas via API | indirect | oui | non | non |
|
||||
| metadata modifiées par VIEW détectées sous la même autorité OWNER | oui, state signature | oui | non | non |
|
||||
| détection corruption/tampering partiel | oui | parsing strict | complément | non |
|
||||
| no-clobber / atomic replace | non | API | oui | non |
|
||||
| protection autres users OS | non | non | best-effort | non |
|
||||
| détection remplacement total valide | non | non | permissions seulement | théoriquement oui, mais **interdite comme dépendance V1** |
|
||||
| détection rollback total valide | non | non | non | théoriquement oui, mais **interdite comme dépendance V1** |
|
||||
| Garantie | Cryptographie du format | Types/capabilities KSP |
|
||||
|------------------------------------------------------------------------|-------------------------------------------------------:|-------------------------:|
|
||||
| confidentialité metadata verrouillées | oui | oui |
|
||||
| confidentialité secret Solana face à VIEW | oui | oui |
|
||||
| indépendance VIEW/OWNER | oui | oui |
|
||||
| VIEW ne signe pas | séparation de clés | oui |
|
||||
| VIEW ne modifie pas Pubkey/alias/notes via API | authentification OWNER des metadata | oui |
|
||||
| VIEW change son propre password | slot VIEW rewrappable sous la même capability metadata | oui, opération dédiée |
|
||||
| VIEW ne change pas password OWNER / activation VIEW / autres key slots | authentification OWNER de l'état de contrôle | oui |
|
||||
| metadata modifiées par VIEW détectées sous la même autorité OWNER | oui, `state_signature` | oui |
|
||||
| détection corruption/tampering partiel | oui | parsing strict |
|
||||
| signature Solana sans OWNER | impossible sous les primitives retenues | API absente hors OWNER |
|
||||
| export secret sans OWNER | secret non déverrouillable | API absente hors OWNER |
|
||||
| mutation Pubkey/alias/notes/OWNER-state sans OWNER | état non authentifiable | API absente hors OWNER |
|
||||
| no-clobber / atomic replace | non | propriété de persistence |
|
||||
| détection remplacement total par un autre wallet valide | hors garantie V1 | hors garantie V1 |
|
||||
| détection rollback total vers une copie valide | hors garantie V1 | hors garantie V1 |
|
||||
|
||||
## 6. Niveau B — VIEW read-only renforcé cryptographiquement
|
||||
Les ACL/permissions OS ne figurent volontairement pas dans cette matrice : elles ne participent pas au modèle de sécurité de `.kspwallet` V1.
|
||||
|
||||
`pre.001` retient **B**.
|
||||
## 6. Niveau B — metadata VIEW read-only + self-service credential
|
||||
|
||||
`pre.001` retient **B** pour les données et capacités OWNER-controlled, tout en accordant explicitement à VIEW une mutation étroite : la rotation de **son propre password VIEW**.
|
||||
|
||||
Le wallet possède une **clé d'administration Ed25519 propre au format**, distincte de la keypair Solana. Sa clé publique de vérification est dans l'enveloppe minimale ; sa clé privée est accessible seulement par OWNER.
|
||||
|
||||
Chaque état persistant valide porte une `state_signature` OWNER calculée sur un transcript déterministe de **tout l'état mutable et de sécurité du fichier**, à l'exception de la signature elle-même : magic/version, autorité publique, key slots et leurs paramètres KDF/wrapping, versions de compartments, algorithmes, nonces et ciphertexts. Toute opération qui change le fichier doit donc être réalisée depuis une capacité OWNER capable de récupérer la clé privée d'administration et de produire une nouvelle signature valide.
|
||||
Chaque état persistant valide porte une `state_signature` OWNER calculée sur un transcript déterministe de l'**état OWNER-controlled** : magic/version, autorité publique, slot OWNER complet, owner-control, metadata, secret, versions/algorithmes couverts, ainsi qu'un **descripteur VIEW stable signé** indiquant notamment si VIEW est activé et l'identité/rôle du slot attendu.
|
||||
|
||||
Conséquence : un détenteur VIEW qui aurait conservé la metadata content key peut techniquement produire un nouveau ciphertext metadata, mais il ne peut pas produire, sous la même autorité OWNER, une nouvelle `state_signature` acceptée. Il ne peut pas davantage modifier un key slot, changer un password, remplacer le compartment secret ou substituer la keypair tout en conservant un état accepté sous l'autorité OWNER originale.
|
||||
Les seuls champs mutables exclus de cette autorisation OWNER sont les **champs de protection du slot VIEW courant** nécessaires à son self-service de password : paramètres Argon2id VIEW autorisés par V1, salt VIEW, nonce et ciphertext du wrapping AEAD de la même capability metadata. Les identifiants d’algorithmes restent imposés par V1 et ne deviennent pas librement mutables par VIEW. Ces champs sont eux-mêmes authentifiés par le wrapping AEAD et liés par AAD au wallet, au rôle VIEW et au descripteur de slot signé. VIEW peut donc rewrapper le même accès metadata sous un nouveau password sans posséder la clé privée d'administration OWNER.
|
||||
|
||||
La cryptographie ne peut pas empêcher un attaquant disposant d'un accès écriture filesystem de modifier physiquement les octets ; elle garantit que ces octets modifiés sont **rejetés** faute d'authentification OWNER valide. Les permissions filesystem complètent cette propriété en empêchant l'écriture lorsque l'OS peut effectivement l'interdire.
|
||||
Conséquence : un détenteur VIEW peut changer son password VIEW, mais ne peut pas produire, sous la même autorité OWNER, une modification acceptée de Pubkey/alias/notes, du slot OWNER, de l'owner-control, du compartiment secret, de l'activation/désactivation de VIEW, du descripteur de slot VIEW ou de la keypair Solana. Modifier ou supprimer le slot VIEW d'une manière incompatible avec son descripteur OWNER-signed est rejeté ; seule la réécriture de ses champs de protection selon le contrat de rotation est admise.
|
||||
|
||||
Limite incompressible : une substitution du **fichier entier** par un autre wallet auto-cohérent, incluant une nouvelle autorité publique OWNER et une nouvelle signature valide, est indétectable par le seul fichier substitué. Cela reste vrai en particulier si l'attaquant connaît le password VIEW et crée le faux wallet avec ce même password. Détecter cette substitution ou un rollback intégral exigerait de comparer à un état de confiance conservé ailleurs ; V1 n'en dépend pas et ne prétend donc pas fournir cette garantie.
|
||||
`ksp-wallet-lib` ne contrôle pas qui peut écrire des octets sur le chemin : les ACL/permissions OS sont hors périmètre. Sa garantie porte sur les capacités acceptées par le format et l'API.
|
||||
|
||||
Un remplacement du **fichier entier** par un autre wallet auto-cohérent crée seulement l'équivalent d'un autre wallet ; il ne révèle pas l'ancien secret et ne donne aucun moyen de signer avec l'ancienne keypair. V1 ne cherche pas à distinguer cette substitution d'un fichier autonome valide ni un rollback intégral vers une ancienne copie valide.
|
||||
|
||||
La keypair Solana **n'est pas** réutilisée comme clé d'administration du format.
|
||||
|
||||
@@ -243,15 +248,26 @@ Sans password OWNER ni clé privée d'administration exfiltrée, un attaquant
|
||||
|
||||
```text
|
||||
modifie Pubkey / alias / notes
|
||||
modifie un paramètre KDF, salt, nonce ou wrapped key
|
||||
remplace / supprime / ajoute un key slot
|
||||
change le password VIEW ou OWNER
|
||||
modifie le slot OWNER ou son password
|
||||
remplace / supprime / ajoute un key slot hors rotation du slot VIEW existant
|
||||
active / désactive / recrée VIEW
|
||||
change le descripteur stable du slot VIEW
|
||||
remplace le compartment secret
|
||||
swap la keypair Solana
|
||||
change les versions/algorithmes couverts
|
||||
change les versions/algorithmes OWNER-controlled
|
||||
```
|
||||
|
||||
Le parseur applique d'abord les bornes structurelles/anti-DoS, puis vérifie la `state_signature` avant tout déverrouillage coûteux ou projection autorisée. Une mutation non signée est un fichier invalide, pas un nouvel état Wallet.
|
||||
La seule exception volontaire est :
|
||||
|
||||
```text
|
||||
VIEW authentifié
|
||||
-> nouveau password VIEW
|
||||
-> nouveaux paramètres/salt/KEK VIEW valides
|
||||
-> rewrap de la même capability metadata
|
||||
-> même descripteur VIEW OWNER-signed
|
||||
```
|
||||
|
||||
Le parseur applique d'abord les bornes structurelles/anti-DoS. Il vérifie l'état OWNER-signed et, lors d'un open VIEW, l'authenticité/binding du slot VIEW fourni. Une mutation de metadata ou d'état OWNER-controlled sans signature OWNER valide est un fichier invalide, pas un nouvel état Wallet.
|
||||
|
||||
Cette garantie est volontairement formulée « sous l'autorité OWNER originale » afin de ne pas confondre **forgery/tampering** avec la substitution totale d'un fichier auto-signé par une autre autorité.
|
||||
|
||||
@@ -291,6 +307,8 @@ exactement 1 slot OWNER
|
||||
0 ou 1 slot VIEW
|
||||
```
|
||||
|
||||
Le slot OWNER et l'état de contrôle sont OWNER-signed. Pour VIEW, l'état OWNER-signed contient un **descripteur stable** (`enabled`, rôle et identifiant de slot ou équivalent wire à figer en `pre.003`). Lorsque VIEW est activé, le fichier doit contenir exactement un slot VIEW correspondant à ce descripteur. Ses paramètres Argon2id autorisés, son salt et son nonce/ciphertext de wrapping restent rotatables sans OWNER, mais les algorithmes V1, son rôle, son identité et son activation ne le sont pas. Le wrapping VIEW utilise un AAD qui lie au minimum format/version, autorité wallet, rôle VIEW et identifiant signé du slot.
|
||||
|
||||
Le wire utilise néanmoins un tableau générique `key_slots` afin qu'un futur `format_version` puisse introduire d'autres rôles sans remodeler toute l'enveloppe.
|
||||
|
||||
### 7.3 Compartiment OWNER control
|
||||
@@ -334,11 +352,13 @@ Seul OWNER reçoit `K_secret` via le control compartment.
|
||||
|
||||
Il faut distinguer :
|
||||
|
||||
**rotation de password VIEW** : nouveau salt/KDF/KEK et nouveau wrapping du même `K_metadata`. L'ancien password ne déverrouille plus le fichier courant, mais cette opération ne révoque pas une `K_metadata` déjà exfiltrée par un VIEW malveillant.
|
||||
**rotation de password VIEW par VIEW** : VIEW authentifié choisit un nouveau password, de nouveaux paramètres/salt/KEK VIEW et rewrappe le même `K_metadata` dans le **même slot VIEW/descripteur signé**. Il ne modifie aucune metadata et n'a pas besoin d'OWNER. L'ancien password ne déverrouille plus le slot courant. Cette opération est une rotation de credential, **pas une révocation cryptographique forte** : un ancien détenteur ayant conservé une ancienne copie/slot ou déjà extrait `K_metadata` peut conserver la capacité de lecture correspondante.
|
||||
|
||||
**révocation/recréation forte de VIEW** : OWNER génère une nouvelle `K_metadata`, rechiffre les metadata, met à jour le control compartment puis crée ou retire le slot VIEW. Une ancienne `K_metadata` ne lit alors plus les **futurs** états metadata. Les anciennes copies du wallet restent naturellement lisibles par qui en possédait déjà les secrets.
|
||||
**rotation de password VIEW par OWNER** : OWNER récupère `K_metadata` via owner-control et peut produire directement un nouveau wrapping VIEW avec un nouveau password, sans connaître l'ancien password VIEW. Le descripteur reste inchangé pour une simple rotation.
|
||||
|
||||
**rotation du password OWNER** : nouveau salt/KDF/KEK et nouveau wrapping de `K_owner_root`, sans changement de keypair Solana ni dépendance à VIEW.
|
||||
**révocation/recréation forte de VIEW** : OWNER génère une nouvelle `K_metadata`, rechiffre les metadata, met à jour le control compartment puis recrée ou retire le slot/descripteur VIEW. Une ancienne `K_metadata` ne lit alors plus les **futurs** états metadata. Les anciennes copies du wallet restent naturellement lisibles par qui en possédait déjà les secrets.
|
||||
|
||||
**rotation du password OWNER** : OWNER génère un nouveau salt/KDF/KEK et un nouveau wrapping de `K_owner_root`, puis renouvelle la `state_signature` OWNER ; aucun changement de keypair Solana ni dépendance à VIEW.
|
||||
|
||||
**keypair Solana** : immuable dans V1 après création/import. Aucun `replace_keypair` n'est exposé. Toute tentative de modifier `secret` ou la Pubkey metadata sans une réécriture OWNER valide échoue sur la `state_signature`; même avec OWNER, l'import d'une autre keypair crée un nouveau `.kspwallet` au lieu de muter l'identité cryptographique existante.
|
||||
|
||||
@@ -447,6 +467,10 @@ Structure de travail à figer par le codec `pre.003` :
|
||||
"magic": "KSPWALLET",
|
||||
"format_version": 1,
|
||||
"owner_auth_public_key": "<base64url>",
|
||||
"view_descriptor": {
|
||||
"enabled": true,
|
||||
"slot_id": "<base64url>"
|
||||
},
|
||||
"key_slots": [
|
||||
{
|
||||
"role": "owner|view",
|
||||
@@ -519,7 +543,7 @@ content keys
|
||||
password-derived keys
|
||||
```
|
||||
|
||||
La clé publique d'administration révèle un fingerprint aléatoire du **format wallet**, pas l'identité blockchain Solana. Elle constitue la racine de vérification **embarquée** de l'état sous la même autorité OWNER ; sa présence ne crée aucune dépendance à un facteur externe.
|
||||
La clé publique d'administration révèle un fingerprint aléatoire du **format wallet**, pas l'identité blockchain Solana. Elle constitue la racine de vérification **embarquée** de l'état sous la même autorité OWNER ; sa présence ne crée aucune dépendance à un facteur externe. Le placement et l'encodage exacts de `view_descriptor` restent à figer en `pre.003` ; son invariant est qu'il est OWNER-signed alors que seuls les champs de protection du slot VIEW correspondant sont self-rotatables.
|
||||
|
||||
### 9.4 Pubkey et secret payload
|
||||
|
||||
@@ -598,7 +622,7 @@ Aucune migration automatique mutante n'est exécutée lors d'un simple `open`. T
|
||||
|
||||
### 9.9 Checksum
|
||||
|
||||
Pas de checksum séparé V1 : AEAD protège chaque ciphertext et la `state_signature` protège l'état sémantique global accepté sous l'autorité OWNER. Un checksum supplémentaire ne fournit pas de garantie de sécurité utile.
|
||||
Pas de checksum séparé V1 : AEAD protège chaque ciphertext/wrapping, la `state_signature` protège l'état OWNER-controlled, et le slot VIEW self-service est authentifié par son wrapping AEAD lié au descripteur OWNER-signed. Un checksum supplémentaire ne fournit pas de garantie de sécurité utile.
|
||||
|
||||
## 10. Authentification, transcript et AAD
|
||||
|
||||
@@ -613,7 +637,9 @@ longueurs explicites
|
||||
entiers en big-endian
|
||||
octets binaires décodés, pas leurs représentations Base64 texte
|
||||
rôle/algorithme/version inclus
|
||||
chaque KDF param/salt/nonce/ciphertext inclus
|
||||
chaque champ OWNER-controlled, KDF/slot OWNER et ciphertext OWNER-controlled inclus
|
||||
descripteur stable VIEW inclus
|
||||
paramètres Argon2id VIEW autorisés + salt + nonce/ciphertext de wrapping du slot VIEW explicitement exclus
|
||||
state_signature elle-même exclue
|
||||
```
|
||||
|
||||
@@ -627,6 +653,7 @@ Chaque opération de wrapping/chiffrement utilise un AAD domain-separated inclua
|
||||
magic/format_version
|
||||
owner_auth_public_key
|
||||
kind de compartiment ou rôle de slot
|
||||
identifiant/descripteur signé du slot lorsqu'il existe
|
||||
identifiants algo/version pertinents
|
||||
paramètres publics nécessaires à lier le ciphertext à son contexte
|
||||
```
|
||||
@@ -639,7 +666,7 @@ Contrat :
|
||||
|
||||
```text
|
||||
ViewPassword / OwnerPassword non Copy, non Clone par défaut, Debug redacted
|
||||
WalletView aucune key de secret et aucune metadata key retenue
|
||||
WalletView aucun secret Solana/OWNER ; seulement matériau VIEW minimal privé pour lecture + rotation de son password
|
||||
WalletOwner secret/root/admin keys privés, sans getter raw public
|
||||
secret/key buffers temporaires Zeroizing/Zeroize lorsque possédés
|
||||
message signé jamais loggé
|
||||
@@ -696,9 +723,10 @@ pubkey()
|
||||
alias()
|
||||
notes()
|
||||
info()
|
||||
rotate_view_password(new_password, ...)
|
||||
```
|
||||
|
||||
Aucune méthode de mutation/signature/export secret/key-slot.
|
||||
`rotate_view_password` est la **seule mutation** disponible à VIEW : elle ne modifie que les champs de protection de son slot courant et rewrappe la même capability metadata. Aucune méthode de mutation Pubkey/alias/notes, signature, export secret, changement OWNER, disable/recreate VIEW ou autre administration n'est exposée.
|
||||
|
||||
`WalletOwner` :
|
||||
|
||||
@@ -716,6 +744,8 @@ rotate_owner_password(...)
|
||||
export_with(...)
|
||||
```
|
||||
|
||||
OWNER peut donc changer son propre password et le password VIEW. Une simple rotation du password VIEW par OWNER n'exige pas de connaître l'ancien password VIEW ; OWNER récupère le matériau metadata depuis owner-control.
|
||||
|
||||
Les mutations persistées sont async et atomiques. `sign()` est locale/CPU et reste naturellement sync.
|
||||
|
||||
## 13. Async / sync
|
||||
@@ -752,24 +782,21 @@ Pour créer/remplacer un `.kspwallet` :
|
||||
|
||||
`create` ne fait jamais d'overwrite implicite. En concurrence, un seul créateur peut publier la destination ; les autres reçoivent `destination_exists`.
|
||||
|
||||
### 14.3 Unix
|
||||
### 14.3 Import vers format natif
|
||||
|
||||
Durcissement visé :
|
||||
Tout import d'un format externe est une **création de wallet natif** :
|
||||
|
||||
```text
|
||||
wallet file créé par KSP 0600
|
||||
répertoire dédié créé par KSP 0700
|
||||
source externe valide
|
||||
-> conversion en nouvelle identité/metadata native
|
||||
-> create no-clobber d'un nouveau fichier .kspwallet
|
||||
```
|
||||
|
||||
KSP ne change pas arbitrairement les permissions d'un parent fourni par l'appelant.
|
||||
L'import ne fournit aucun mode overwrite/replace d'un `.kspwallet` existant et ne sert jamais à remplacer la keypair d'un wallet déjà créé. Une destination existante retourne `destination_exists`.
|
||||
|
||||
Les sources secrètes d'import doivent être des fichiers réguliers et les symlinks sont refusés par défaut pour réduire les ambiguïtés/TOCTOU usuelles. La stratégie exacte est testée dans la tranche persistence/import.
|
||||
### 14.4 Écriture interrompue
|
||||
|
||||
### 14.4 Autres plateformes
|
||||
|
||||
Aucune promesse POSIX `0600/0700` sur Windows. La documentation distingue garanties portables, ACL/permissions système et durcissement Unix.
|
||||
|
||||
Un crash peut laisser un temp artifact complet à nettoyer ; l'invariant prioritaire est de ne pas transformer l'ancien wallet valide en fichier partiellement remplacé.
|
||||
Un crash peut laisser un temp artifact complet à nettoyer ; l'invariant prioritaire est de ne pas transformer l'ancien wallet valide en fichier partiellement remplacé. Les ACL/permissions du système d'exploitation ne font pas partie des garanties de `ksp-wallet-lib`.
|
||||
|
||||
## 15. Erreurs et non-oracle
|
||||
|
||||
@@ -940,23 +967,28 @@ L'injection de random déterministe reste privée aux tests/codec fixtures ; l'A
|
||||
### 19.2 VIEW/OWNER
|
||||
|
||||
- VIEW lit seulement metadata autorisées ;
|
||||
- aucune signature/mutation/admin/export via type VIEW ;
|
||||
- VIEW peut changer son propre password VIEW ;
|
||||
- VIEW ne peut modifier ni Pubkey/alias/notes, ni OWNER, ni activation/descripteur VIEW ;
|
||||
- aucune signature/export secret/admin OWNER via type VIEW ;
|
||||
- OWNER fonctionne sans VIEW ;
|
||||
- OWNER signe et administre ;
|
||||
- mauvais rôle/password échoue sans fuite ;
|
||||
- salts/KDF material indépendants ;
|
||||
- VIEW ne dérive pas OWNER/secret ;
|
||||
- modification metadata par détenteur VIEW sans admin signing key rejetée ;
|
||||
- modification d'un key slot/KDF/wrapped key par détenteur VIEW rejetée ;
|
||||
- tentative de changer password VIEW/OWNER sans OWNER rejetée ;
|
||||
- modification du slot OWNER ou du descripteur/activation VIEW par détenteur VIEW rejetée ;
|
||||
- rotation valide des seuls paramètres Argon2id VIEW autorisés, salt et nonce/ciphertext de wrapping du slot VIEW courant par VIEW acceptée ;
|
||||
- tentative de changer password OWNER via VIEW rejetée ;
|
||||
- substitution du ciphertext secret/keypair sans OWNER rejetée ;
|
||||
- `state_signature` invalide/manquante rejetée avant projection ;
|
||||
- substitution totale explicitement non promise.
|
||||
|
||||
### 19.3 Rotation/revocation
|
||||
|
||||
- rotation VIEW conserve keypair/Pubkey ;
|
||||
- old password VIEW n'ouvre plus le slot courant ;
|
||||
- rotation VIEW par VIEW conserve keypair/Pubkey/metadata et ne change que son credential ;
|
||||
- rotation VIEW par OWNER fonctionne sans ancien password VIEW ;
|
||||
- old password VIEW n'ouvre plus le slot courant après rotation normale ;
|
||||
- limites de révocation d'un ancien détenteur ayant conservé `K_metadata`/une ancienne copie explicitement testées/documentées ;
|
||||
- rotation OWNER conserve keypair/Pubkey ;
|
||||
- old password OWNER n'ouvre plus le slot courant ;
|
||||
- disable/recreate VIEW ne nécessite pas ancien password VIEW ;
|
||||
@@ -979,8 +1011,8 @@ L'injection de random déterministe reste privée aux tests/codec fixtures ; l'A
|
||||
- concurrence no-clobber ;
|
||||
- replace atomique ;
|
||||
- fault injection avant publication préserve l'ancien wallet ;
|
||||
- permissions Unix ;
|
||||
- symlink/source handling ;
|
||||
- import vers destination nouvelle/no-clobber ;
|
||||
- import vers destination existante rejeté sans écrasement ;
|
||||
- éventuels temp remnants documentés sans corruption du wallet publié.
|
||||
|
||||
### 19.6 Architecture
|
||||
@@ -1017,11 +1049,11 @@ Conclusion : **pas de rescoping fonctionnel**, mais split supplémentaire avant
|
||||
|
||||
```text
|
||||
pre.001 audit bot2/bot3 + deps actuelles + threat model + VIEW/OWNER + format/API + sizing
|
||||
pre.002 crate foundation + capability/password/info types + erreurs + logging contract + canaries architecture
|
||||
pre.002 crate foundation + capability/password/info types (VIEW self-rotation only, OWNER admin) + erreurs + logging contract + canaries architecture
|
||||
pre.003 codec JSON strict + limites + key-slot/envelope DTOs + transcript/AAD codec + contrat docs/formats + spec V1 initiale
|
||||
pre.004 benchmark KDF + Argon2id/XChaCha wrapping + content keys + deterministic crypto vectors in-memory
|
||||
pre.005 owner-control + metadata/secret compartments + create/open VIEW/OWNER + state signature niveau B
|
||||
pre.006 persistence async/atomic/no-clobber + Unix hardening + fault/concurrency tests
|
||||
pre.006 persistence async/atomic/no-clobber + interrupted-write + fault/concurrency tests
|
||||
pre.007 signature Solana + alias/notes + rotations passwords + disable/recreate VIEW avec rekey metadata
|
||||
pre.008 import/export adapters + Solana CLI JSON + generic keypair Base58 + inspect
|
||||
pre.009 audit security/interoperability/compliance + adversarial vectors/tests + cargo trees
|
||||
@@ -1108,12 +1140,14 @@ KSPWALLET_V1.md permet une implémentation indépendante sans consulter le code
|
||||
.kspwallet V1 est spécifié hors code et couvert par vecteurs publics auto-contenus
|
||||
VIEW/OWNER sont indépendants cryptographiquement et dans l'API
|
||||
Pubkey/alias/notes restent cachés verrouillé
|
||||
VIEW ne peut pas signer/admin/exporter via l'API
|
||||
niveau B rejette toute mutation de l'état couvert sous la même autorité OWNER sans signature OWNER valide
|
||||
VIEW connu ne permet ni changement de password/key slot ni swap de keypair sous l'autorité OWNER originale
|
||||
VIEW ne peut pas signer/exporter ni modifier Pubkey/alias/notes/OWNER via l'API
|
||||
VIEW peut changer uniquement son propre password en rewrappant la même capability metadata dans son slot courant
|
||||
niveau B rejette toute mutation de l'état OWNER-controlled sous la même autorité OWNER sans signature OWNER valide
|
||||
VIEW connu ne permet ni changement du password OWNER/descripteur VIEW/slot OWNER ni swap de keypair sous l'autorité OWNER originale
|
||||
OWNER peut changer son propre password et le password VIEW sans dépendre de VIEW
|
||||
limite substitution/rollback complet est documentée sans surpromesse
|
||||
keypair V1 est immuable après création/import
|
||||
rotation password ne change pas keypair
|
||||
rotation de password VIEW ou OWNER ne change pas keypair
|
||||
OWNER gère VIEW sans ancien password VIEW
|
||||
révocation forte VIEW rekey les metadata futures
|
||||
sign() n'exige pas d'extraction publique du secret
|
||||
|
||||
Reference in New Issue
Block a user