epic: keys and keystore #2

Closed
opened 2026-09-15 12:34:51 +00:00 by grenade · 2 comments
Owner

Goal

A user can create a wallet from a fresh BIP39 mnemonic, restore one from a phrase or a quantus-cli wallet file, and sign with it, with the secret material never leaving Rust and never touching disk unencrypted. The keystore file format is quantus-cli's (Argon2id + AES-256-GCM, EncryptedWallet), so a wallet moves freely between this app, the CLI and the browser extension.

Facts the design rests on

  • Quantus signs with ML-DSA. The chain's Signature is DilithiumSignatureScheme { Dilithium87, Dilithium65 } and carries the public key on the wire because the account id is Poseidon2 of the public key.
  • Derivation is qp-rusty-crystals-hdwallet at m/44'/189189'/account'/change'/index', every level hardened. The other Quantus wallets use index 0' for ML-DSA-87 and 1' for ML-DSA-65; new accounts default to 65.
  • Extrinsics are signed under the FIPS 204 context QUANTUS_EXTRINSIC from spec 148; mainnet is at 152. The context is a property of the chain profile, not of the key.
  • The CLI keystore already zeroizes, redacts Debug, and verifies the decrypted key against the stored address before use. Match all three.

Operator-owned decisions

  • OS keychain integration (Secret Service, Keychain, Credential Manager) for the unlock secret, or password-only with an auto-lock timer. Default: password-only first; keychain is a follow-up child, not a blocker.

Definition of done

A mnemonic created here restores in quantus-cli 2.x to the same qz… address and checkphrase, and a wallet file exported by quantus-cli opens here. A signature produced here over a Quantus signing payload verifies on a dev node. No test, log line or Debug output can print a seed, mnemonic or secret key.

## Goal A user can create a wallet from a fresh BIP39 mnemonic, restore one from a phrase or a quantus-cli wallet file, and sign with it, with the secret material never leaving Rust and never touching disk unencrypted. The keystore file format is quantus-cli's (Argon2id + AES-256-GCM, `EncryptedWallet`), so a wallet moves freely between this app, the CLI and the browser extension. ## Facts the design rests on - Quantus signs with ML-DSA. The chain's `Signature` is `DilithiumSignatureScheme { Dilithium87, Dilithium65 }` and carries the public key on the wire because the account id is Poseidon2 of the public key. - Derivation is `qp-rusty-crystals-hdwallet` at `m/44'/189189'/account'/change'/index'`, every level hardened. The other Quantus wallets use index `0'` for ML-DSA-87 and `1'` for ML-DSA-65; new accounts default to 65. - Extrinsics are signed under the FIPS 204 context `QUANTUS_EXTRINSIC` from spec 148; mainnet is at 152. The context is a property of the chain profile, not of the key. - The CLI keystore already zeroizes, redacts `Debug`, and verifies the decrypted key against the stored address before use. Match all three. ## Operator-owned decisions - OS keychain integration (Secret Service, Keychain, Credential Manager) for the unlock secret, or password-only with an auto-lock timer. **Default: password-only first; keychain is a follow-up child, not a blocker.** ## Definition of done A mnemonic created here restores in quantus-cli 2.x to the same `qz…` address and checkphrase, and a wallet file exported by quantus-cli opens here. A signature produced here over a Quantus signing payload verifies on a dev node. No test, log line or `Debug` output can print a seed, mnemonic or secret key.
grenade added the epic label 2026-09-15 12:38:41 +00:00
Author
Owner

Children, in dependency order: #14 (ML-DSA key schemes) → #15 (quantus-cli keystore) and #16 (mnemonic lifecycle) → #17 (unlock session). OS keychain is a follow-up to #17, filed when #17 lands.

Children, in dependency order: #14 (ML-DSA key schemes) → #15 (quantus-cli keystore) and #16 (mnemonic lifecycle) → #17 (unlock session). OS keychain is a follow-up to #17, filed when #17 lands.
Author
Owner

Done. #14 through #17 are closed by commits on main. Against the definition of done:

  • A mnemonic derived here matches quantus-cli 2.2.2 for both schemes at three paths each (six vectors), and the checkphrase for the dev phrase's ML-DSA-65 account matches quantus wallet view (Indicate-Dew-Undamaged-Axis-Obtain).
  • Eight real CLI wallet files plus the two dev-chain accounts open here; a wallet written here lists in quantus wallet list with the expected address.
  • A signature produced here verifies on a node: Planck's public node refused an unfunded transfer for payment, not signature, and refused the same transfer signed under the empty context as a bad signature; the dev node then accepted real transfers (#22).
  • No test, log or Debug prints a secret: every holder redacts, and a Linux test scans the process's writable memory after lock() for a runtime-built seed and secret and finds neither, in debug and release.

Deferred as its own follow-up when wanted: the OS keychain for the unlock secret. Password-only with a ten-minute idle lock is what ships.

Done. #14 through #17 are closed by commits on `main`. Against the definition of done: - A mnemonic derived here matches quantus-cli 2.2.2 for both schemes at three paths each (six vectors), and the checkphrase for the dev phrase's ML-DSA-65 account matches `quantus wallet view` (`Indicate-Dew-Undamaged-Axis-Obtain`). - Eight real CLI wallet files plus the two dev-chain accounts open here; a wallet written here lists in `quantus wallet list` with the expected address. - A signature produced here verifies on a node: Planck's public node refused an unfunded transfer for *payment*, not signature, and refused the same transfer signed under the empty context as a bad signature; the dev node then accepted real transfers (#22). - No test, log or `Debug` prints a secret: every holder redacts, and a Linux test scans the process's writable memory after `lock()` for a runtime-built seed and secret and finds neither, in debug and release. Deferred as its own follow-up when wanted: the OS keychain for the unlock secret. Password-only with a ten-minute idle lock is what ships.
Sign in to join this conversation.
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: blackbeard/wallet#2