Encrypt an existing secret with a passkey
A secret vault encrypts a recovery phrase, private key, or other byte string behind a passkey. This recipe encrypts a phrase and unlocks it later.
Prerequisites:
@category-labs/merainstalled.- A place to keep vault JSON (
localStoragehere; a backend or sync service works the same).
Create and persist the vault
Section titled “Create and persist the vault”createSecretVaultWithNewPasskey generates a fresh 32-byte salt per vault, creates the passkey, and encrypts the secret. The salt and credential metadata are stored in the returned vault (vault format).
import { createSecretVaultWithNewPasskey } from "@category-labs/mera";
const rpId = location.hostname;
const phrase = "legal winner thank year wave sausage worth useful legal winner thank yellow";const secret = new TextEncoder().encode(phrase);
const vault = await createSecretVaultWithNewPasskey({ rp: { id: rpId, name: "Example" }, user: { name: "account@example.com", displayName: "Example account" }, secret,});localStorage.setItem("app.vault", JSON.stringify(vault));A private key is encrypted the same way: pass its raw bytes as secret instead of encoded text.
Unlock
Section titled “Unlock”The unlock runs one ceremony, pinned automatically to the credential stored in the vault:
import { decryptSecretVaultWithPasskey, parseSecretVault,} from "@category-labs/mera";
async function unlockPhrase(): Promise<string> { const raw = localStorage.getItem("app.vault"); if (raw === null) throw new Error("No vault on this device yet.");
const vault = parseSecretVault(raw); const secret = await decryptSecretVaultWithPasskey({ rpId, vault }); return new TextDecoder().decode(secret);}parseSecretVault is the boundary for the untrusted stored JSON.
See also
Section titled “See also”- Secret vaults: how a vault works and when to use one.
- createSecretVaultWithExistingPasskey: encrypt another secret with the same passkey.
- Secret vault format: the stored JSON, field by field.