A must-have per the UX decision in quantus/extension#8: the extension has to be able to take a wallet a user already has. My earlier recommendation against this was withdrawn — the reasoning was that a file importer would pull the mnemonic into storage, which is a property of an implementation rather than of the format. This one derives and discards. Converts at the edge rather than teaching the keyring a second container. Decrypt (Argon2id -> AES-256-GCM), take the key material, and hand back a plain keypair for the caller to re-encrypt as the extension's own PKCS8 under a password the user chooses. decodePair does not learn about Argon2 and the keyring keeps exactly one on-disk format. The CLI stores a mnemonic in every HD wallet. This returns `hadMnemonic` and not the phrase — the posture is that a storage password unlocks signing and nothing on disk regenerates the tree, and an import must leave us holding exactly what importing the same mnemonic by hand would leave us holding. Matching upstream, which stores key material only. No new dependencies: @noble/hashes/argon2 was already a util-crypto dependency and AES-GCM is WebCrypto. Async only because WebCrypto has no synchronous form, which is a second reason this belongs at the edge — createFromJson is sync and should stay so. Three things are refused rather than worked around: Argon2 parameters are read from the file, not assumed. They are stored because they are expected to change, and a build that hardcoded m=19456,t=2,p=1 would reject a correct password on an older or newer wallet — the least useful thing it could say. Non-empty kyber_ciphertext/kyber_public_key, and any encryption_version other than 2, are refused with a message. Those fields are an ML-KEM envelope mode that is planned or optional; decrypting by the path we know and ignoring them would fail later and more confusingly, most likely as a bad-password error. The address sits outside the encrypted blob, so it is the one field an attacker can edit without the password. cliWalletAddressMatches is exposed separately so a caller can say "this file's address does not match its key" rather than "wrong password" — a user can act on the difference. Fixtures are genuine CLI 2.2.2 output, not blobs this repo encrypted; testing a decoder against its own encryption proves only self-consistency. They contain no secret: the mnemonic inside each is the public Substrate dev phrase and the password is empty, which is the only reason committing a decryptable wallet is acceptable. The strongest test reaches the same account two ways — through the CLI container and by deriving from that phrase ourselves. Refs quantus/common#7 Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_012uDUodEcRbBwNRi3UCmw8f
@polkadot/util-crypto
Various useful cyrpto utility functions that are used across all projects in the @polkadot namespace. It provides utility functions with additional safety checks, allowing not only for consistent coding, but also reducing the general boilerplate.
Usage
Installation -
yarn add @polkadot/util-crypto
Functions can be imported as follows:
import { mnemonicGenerate } from '@polkadot/util-crypto';