Security Model
Moi Wallet is non-custodial. Your keys are generated on your device, encrypted before storage, and never transmitted to Moi Wallet servers or Sarva Labs infrastructure. This page explains how your seed phrase, encryption, and platform storage work — in plain language where possible, with technical detail where it matters.
The Seed Phrase
Your 12-word seed phrase is the root credential for your entire wallet.
BIP-39
Moi Wallet follows the BIP-39 standard. At wallet creation, 128 bits of randomness are encoded as 12 words chosen from a fixed list of 2,048 words. This mnemonic is human-readable but represents a cryptographic secret of the same strength as a long random key.
HD derivation (BIP-32 / BIP-44)
From this single seed phrase, all accounts and keys are derived using hierarchical deterministic (HD) wallet standards:
- BIP-32 defines how a master key branches into child keys
- BIP-44 assigns each account a unique derivation path (account index)
You do not need a new seed phrase for each account — one phrase controls every account derived from it.
What you must never do
| Action | Consequence |
|---|---|
| Lose the seed phrase | Permanent, unrecoverable loss of wallet access. No one can restore it for you. |
| Share the seed phrase | Immediate, total compromise — anyone with the phrase can steal all funds. |
| Store it digitally in plain text | Screenshots, cloud notes, and email are vulnerable to theft and leaks. |
Encryption
The seed phrase is never stored in plain text on your device or in the extension. Both clients encrypt the mnemonic before persistence and derive encryption keys from your password using scrypt.
Mobile app
| Parameter | Value |
|---|---|
| KDF | scrypt (scryptSync) |
| N | 4096 |
| r | 8 |
| p | 1 |
| Derived key length | 32 bytes (used directly as the AES key) |
| Salt | 16 random bytes (password_salt) |
| Cipher | AES-256-GCM |
| IV | 12 random bytes per encryption |
| Authentication | 16-byte GCM auth tag appended to ciphertext |
Stored values: encrypted_seed (ciphertext + tag), seed_iv, and password_salt.
Chrome extension
| Parameter | Value |
|---|---|
| KDF | scrypt |
| n | 4096 (2 << 11) |
| r | 8 |
| p | 1 |
| Derived key length | 32 bytes |
| Salt | 32 random bytes |
| Cipher | AES-128-CTR (first 16 bytes of derived key) |
| IV | 16 random bytes |
| Integrity | Keccak-256 MAC over derivedKey[16:32] + ciphertext |
The encrypted payload is stored as a keystore object (cipher, cipherText, cipherparams, kdf, kdfparams, mac) under the key vault::keystore in chrome.storage.local.
Shared principles
- Your password is never stored — only a salt and encrypted ciphertext persist on disk
- The encryption key is derived at unlock time from your password + salt via scrypt
- If the password is wrong, decryption fails (GCM auth tag mismatch on mobile; MAC mismatch on extension)
- During an unlocked session, the decrypted seed phrase exists in memory only for signing operations
Each time you unlock the wallet, scrypt derives a fresh encryption key from your password and the stored salt. Support cannot recover your password — only you can decrypt the wallet with the correct password or by re-importing your seed phrase.
Storage — Mobile App
Sensitive wallet credentials are stored via Expo SecureStore, which maps to platform-native secure storage. Non-sensitive app data (such as transaction history) uses a local SQLite database.
What is stored in SecureStore
| Key | Contents |
|---|---|
encrypted_seed | AES-256-GCM encrypted seed phrase (ciphertext + auth tag) |
seed_iv | IV used for seed phrase encryption |
password_salt | scrypt salt for password key derivation |
derived_key_biometric | Optional — scrypt-derived key, stored with biometric gate |
All SecureStore entries use keychainAccessible: AFTER_FIRST_UNLOCK_THIS_DEVICE_ONLY (iOS Keychain equivalent: accessible after first device unlock, not transferable to other devices).
iOS
- Values are stored in the iOS Keychain, sandboxed to the Moi Wallet app
- On supported devices, Keychain can leverage the Secure Enclave for hardware-backed protection
- Biometric unlock uses Keychain
requireAuthenticationto gate access to the stored derived key
Android
- Expo SecureStore uses EncryptedSharedPreferences — values encrypted with AES-256-GCM, with master keys held in the Android Keystore
- Data is inaccessible to other apps without root access
- Biometric unlock uses the platform authentication API before releasing the stored derived key
SQLite (moi_wallet.db)
Local interaction history is cached in SQLite for display and sync. This database does not contain your seed phrase or private keys.
Biometrics (optional)
After initial password setup, Moi Wallet asks whether you want to use biometrics to unlock the wallet. If your device has biometrics enabled in system settings (Face ID, Touch ID, or fingerprint), you can proceed and allow biometrics to unlock the wallet on subsequent opens.
Biometrics gate access to a pre-derived encryption key stored in SecureStore — they do not replace your seed phrase or password for wallet recovery. If biometrics are disabled at the OS level, the prompt will not succeed until you enable them in your device settings.
Storage — Chrome Extension
chrome.storage.local
The extension persists wallet state in chrome.storage.local via the ExtensionStorage helper. The raw seed phrase is never written in plain text.
| Storage key | Contents |
|---|---|
vault::keystore | Encrypted keystore object (scrypt + AES-128-CTR + MAC) |
wallet::moi-id | Primary MOI ID |
wallet::accounts | Account UID list |
wallet::selected-account / wallet::selected-sub-account | Active account selection |
wallet::account-sync | Account sync status |
Per-account keys (wallet::account::*) | Account metadata |
| Network, permissions, activity log | App configuration and DApp permissions |
In-memory vault session
When unlocked, the decrypted seed phrase is held in an in-memory SecureVaultHandler map (runtime background process). On lock (manual or after 30 minutes of inactivity), the in-memory copy is deleted. The encryption key and decrypted mnemonic are not persisted between locked sessions.
Related guides
- Recovering Your Wallet After Device Loss
- Create a New Wallet
- Import / Restore a Wallet
- Security Settings
- Developer Reference — open-source repositories and architecture