Introducing Seed Vault: Secure On-Chain Seed Phrase Storage with vetKeys on ICP

Introducing Seed Vault: Secure On-Chain Seed Phrase Storage with vetKeys on ICP

Hey everyone in the ICP community,

I’m excited to share a project I’ve been working on called Seed Vault – a simple, secure app deployed on the Internet Computer Protocol (ICP) blockchain that lets users encrypt and store their seed phrases online using vetKeys. I know what you’re thinking: “Storing seed phrases online? That’s a big no-no!” And you’re absolutely right – in most cases, it’s a terrible idea due to the risks of hacks, leaks, or centralized vulnerabilities. But with ICP’s vetKeys technology, this app demonstrates how you could theoretically do it safely in a decentralized way, without ever exposing your plaintext seeds to the backend or anyone else. Of course, I’d still recommend air-gapped hardware wallets for your most critical assets, but Seed Vault shows off some cool ICP features for secure, encrypted storage.

The app is live and fully functional, so feel free to check it out, test it, or even deploy your own instance. I’ll dive into the details below.

Live Demo and Repo

If you’re new to vetKeys, it’s ICP’s verifiably encrypted threshold key derivation system – basically, it allows canisters to derive encrypted keys on-demand in a distributed, secure manner without a single point of failure. For more on vetKeys, check out the official docs or the encrypted notes tutorial that inspired parts of this project.

What Does Seed Vault Do?

Seed Vault is a basic web app that lets you:

  • Authenticate via Internet Identity (II) for seamless, secure login.
  • Store multiple seed phrases (or passwords) under custom titles, encrypted on-chain using vetKeys and AES-GCM.
  • View a list of your stored seed titles without decrypting anything (no cost or exposure).
  • Decrypt individual seeds on-demand by clicking a button next to the title – but only after confirming the billing cost.
  • Automatically hide and clear decrypted seeds from memory after 5 minutes for added security.
  • Transfer ICP out of your subaccount if needed.

Here’s a quick walkthrough of the user flow:

  1. Login: Use Internet Identity to authenticate. No passwords, just your ICP principal.
  2. Add a Seed: Enter a title (e.g., “My Ledger Wallet”) and your seed phrase. The app derives a unique vetKey for encryption, encrypts locally in your browser, and stores the ciphertext on the backend canister.
  3. View List: See all your seed titles in a list. No decryption happens here – it’s free and safe.
  4. Decrypt a Seed: Click “Decrypt” next to a title. You’ll get a confirmation prompt with the exact ICP cost (dynamically calculated). After paying, the app fetches the ciphertext, derives the decryption key via vetKeys, and shows the plaintext temporarily.
  5. Billing Confirmation: Before any paid operation (encrypt/decrypt), a popup shows the cost in ICP, how much you’ll be billed, and asks for confirmation. This prevents surprises.
  6. Auto-Top-Up: Collected ICP fees are automatically converted to cycles to keep the backend canister running indefinitely.

The app enforces limits like 420 characters per seed, 100 characters per title, and 50 seeds per user to keep things efficient and secure.

Key Features and Unique Setup

What makes Seed Vault stand out is how it leverages ICP’s native capabilities for security and sustainability:

1. vetKeys Integration for Secure Encryption

  • Each seed is encrypted using a unique symmetric key derived from vetKeys. The key is generated on-demand via ICP’s threshold key derivation, meaning no single node holds the master key – it’s distributed across the subnet.
  • Encryption happens client-side in your browser using AES-GCM (with a random IV for each seed).
  • Decryption also stays client-side: The backend only stores ciphertext and never sees plaintext or keys.
  • This setup ensures that even if the canister is compromised (unlikely on ICP), your seeds remain encrypted. vetKeys’ verifiability adds an extra layer, proving the derived keys are correct without trusting a central authority.
  • Inspired by the encrypted notes tutorial, but extended for seed phrases with dynamic billing.

2. Dynamic Pricing and Auto-Top-Up

  • Operations like encrypting/decrypting cost cycles, which are billed in ICP via dynamic exchange rates from the XRC canister (ICP/XDR rates refreshed every 5 minutes).
  • If live rates fail (e.g., due to network issues), it falls back to cached or hardcoded estimates to keep the app running smoothly.
  • Users are charged exactly for what they use: ~0.0001 ICP ledger fee + a small buffer for cycles. No subscriptions – pay per operation.
  • Collected ICP is automatically converted to cycles via the Cycles Minting Canister (CMC) and withdrawn from the cycles ledger. This “auto-top-up” keeps the backend canister funded forever without manual intervention.
  • Pricing includes safety caps (e.g., max 1 ICP per op) and rate deviation checks to prevent overcharges.

3. Security-Focused UX

  • Individual Decryption: Only decrypt what you need, when you need it. The list view is free and doesn’t expose anything.
  • Billing Popups: Before charging, a popup confirms the exact cost and requires user approval. For decryption, it warns about trusted devices.
  • Auto-Clear: Decrypted seeds are stored in sessionStorage and cleared after 5 minutes (with a countdown). They’re also hidden by default.
  • Rate Limiting: 20 ops/hour per user, 200 global, to prevent abuse.
  • Audit Logs: A short history of your actions (e.g., “Added seed X”) is available.
  • Content-Security-Policy: Hardened headers in ic-assets.json5 to mitigate XSS.
  • No Plaintext Storage: Backend only holds encrypted blobs; keys are derived fresh each time.

Seed Vault proves you could safely store backups or less-critical phrases online on ICP without trusting a centralized service. Everything’s decentralized, encrypted, and verifiable.

Tech Stack

  • Backend: Motoko canister handling storage, vetKeys derivation, ICP ledger transfers, and cycle conversions.
  • Frontend: React app with AuthClient for II login, CryptoJS for AES-GCM fallback (WebCrypto primary), and vetKeys library for key handling.
  • Deployment: dfx for local dev; deployed on mainnet with custom canister IDs.
  • Dependencies: @dfinity/agent, @dfinity/vetkeys, crypto-js, etc.

The code is open-source – feel free to audit, fork, or contribute. It’s a great starting point if you’re building encrypted apps on ICP.

Limitations and Warnings

  • Not for Production Secrets: This is a demo/proof-of-concept. Always back up seeds offline.
  • Costs Fluctuate: ICP prices change with exchange rates – check the app’s pricing status.
  • Browser Security: Decryption happens in-browser, so use on trusted devices only. Mobile Safari may have quirks with popups.
  • No Recovery: If you lose your II, your seeds are gone (by design for security).
  • Test Thoroughly: I’ve tested on mainnet, but always use small amounts first.

Feedback and Next Steps

I’d love your thoughts! Does this spark ideas for vetKeys use cases? Any bugs, suggestions, or improvements?

Thanks for checking it out – let’s build more secure dApps on ICP! :rocket:

8 Likes