Import quantus-cli wallet files #7
Reference in New Issue
Block a user
Delete Branch "%!s()"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
A must-have, per the UX decision in quantus/extension#8. Reverses the recommendation in #3, where the reasoning against it was withdrawn.
What a CLI wallet looks like
~/.quantus/wallets/<name>.json, fromquantus-cli2.2.2:Argon2id → AES-256-GCM, wrapping JSON:
Read the Argon2 parameters from
argon2_paramsrather than hardcoding them. They are in the file because they are expected to change, and a hardcodedm=19456,t=2,p=1would fail to open older or newer wallets with a wrong-password error rather than a useful one.Convert at the edge
Decrypt, take
keypair.public_key/private_key/scheme, and hand the pair tokeyring.addPairre-encrypted as the extension's own PKCS8 under a password the user chooses. The keyring stays single-format — this is not a second container inside it, anddecodePairdoes not learn about Argon2.Derive and discard the mnemonic. The CLI stores one; we do not, and the UX decision is explicit that a storage password unlocks signing and nothing regenerates the tree from disk. Importing a CLI wallet must leave us holding exactly what importing the same mnemonic by hand would leave us holding — no more.
The
schemefield maps directly:ml-dsa-65→dilithium65,ml-dsa-87→dilithium87, which is alreadySCHEME_NAMEin@quantus/crypto.No new dependencies
@noble/hashes/argon2, already autil-cryptodependencycrypto.subtle), available in an MV3 service worker and in nodeWebCrypto is async, which is why this belongs at the import edge rather than inside
createFromJson: that path is synchronous and should stay so. An import is a one-shot user action that can await.A real CLI wallet has already been decrypted through exactly this pair of primitives, so the approach is confirmed rather than assumed.
Verify, do not trust
The file carries an
addressalongside the encrypted key. Check that the imported public key hashes to it, and refuse the import if not — the same reasoning as the tampered-address check in #3. A file whose address does not match its key would otherwise produce an account displaying an address it cannot sign for.The fields that are empty today
kyber_ciphertextandkyber_public_keyare present but empty, andencryption_versionis 2. That is an ML-KEM envelope mode either planned or optional. Refuse a file with non-empty kyber fields, clearly, rather than ignoring them and decrypting by the path we know — a wallet encrypted to an ML-KEM key is not one we can open, and silently treating it as if it were would fail confusingly at best.Treat an unrecognised
encryption_versionthe same way.Acceptance
quantus-cliwallet imports and produces the address the file claimsencryption_version, are refused with a message saying whyaddressdisagrees with its key is refusedChecked against
main(7f23d0a60). The library side is done, but nothing uses it yet, and it has one gap of its own.Done (
e55352aa4,74e1e0cc6):Remaining:
dilithiumFromCliWalletreturns a key without checking it against the file's address. That check is a separate helper,cliWalletAddressMatches, which a caller has to remember to call, and the comment nearcliWallet.ts:194wrongly implies it is already done. Refuse a mismatch inside the import.dilithiumFromCliWallet, so a user cannot import aquantus-cliwallet file today. It needs:Correction: earlier today I listed this issue as done. It isn't.