Turn your Android phone into a secure Bitcoin hardware wallet and signing device
MetroVault is a secure, offline Android signing device application designed to turn your Android phone into a cold storage hardware wallet. Built with modern Android technologies on top of vaultovich, MV's own auditable Kotlin Bitcoin library, it prioritizes security and simplicity. Supports both single-sig and multi-sig wallets.
The primary goal of MetroVault is to provide a completely offline environment for managing Bitcoin private keys. It acts as a signer for your watch-only wallets (like BlueWallet, Sparrow, or Electrum) running on online devices. By keeping your keys on a device that never connects to the internet (air-gapped), you significantly reduce the attack surface for theft and malware.
Key Benefits:
- 💰 Free - Use any Android phone as a hardware wallet
- 🔒 Secure - Air-gapped operation with military-grade encryption
- 🔨 Open Source - Fully auditable code, no hidden backdoors
- 🎨 Modern - Beautiful Material 3 design with Jetpack Compose
| Feature | Description |
|---|---|
| Air-Gapped Operation | Designed for devices with no internet (Airplane mode, WiFi/Bluetooth disabled) |
| Dual-Layer Encryption | AES-256-GCM with PBKDF2 (600k iterations) + Android Keystore |
| Biometric Authentication | Hardware-backed fingerprint/face unlock with crypto binding |
| Plausible Deniability | Separate "Main" and "Decoy" wallets with different passwords |
| Brute-Force Protection | Exponential backoff rate limiting with a 24-hour lockout after 20 attempts; changing the device clock can't skip it |
| Automatic Wipe | Optional feature to completely wipe sensitive data after 4 unsuccessful login attempts |
| Duress Unlock | Optional password or fingerprint that wipes all app data at unlock and opens a throwaway wallet so the screen looks normal |
| Clipboard Auto-Clear | Sensitive values copied to the clipboard are cleared after 20 seconds |
- Multi-Type Support: Native SegWit (
bc1q...), Taproot (bc1p...), Nested SegWit (3...), Legacy (1...), Silent Payments (sp1q...) - Multi-Sig Support: Import and sign for collaborative custody wallets (2-of-3, 3-of-5, etc.)
- Silent Payments (BIP-352): Create dedicated SP wallets, send to
sp1q…recipients from any wallet, and sign spends of received SP outputs — all air-gapped. The spend key never leaves the device; only the scan key is exported (spscan…/ descriptor) to the watching wallet. - Address Type & Network: Switch any single-seed wallet between Taproot / Native SegWit / Nested SegWit / Legacy / Silent Payments, and between mainnet and testnet, without re-importing the seed
- Passphrase Support: Optional BIP-39 passphrase with choice to save locally or keep in session memory only; a home-screen shortcut applies a session passphrase to an existing wallet
- Testnet4 Support: Import or create Testnet wallet for testing and development
- Custom Entropy: Add your own randomness via dice rolls or coin flips
- Mnemonic Tools: Built-in checksum calculator and validator
- BIP-85 Derivation: Generate child seeds (12/24 words) and secure passwords from your master seed
- XPRIV Export: Export wallet's extended private key (if needed)
- PSBT Workflow (BIP-174 + BIP-370 v2): Partially Signed Bitcoin Transactions for single-sig and multi-sig
- Multi-Sig Signing: Sign your part of collaborative custody transactions (with locally saved keys)
- Silent-Payment Signing: Sign sends to
sp1q…recipients (the derivedbc1p…is computed on-device and shown alongside thesp1q…on the confirmation screen) and sign spends of received SP outputs viaPSBT_IN_SP_TWEAK(BIP-374) - Fee-Attack Protection: Multi-input SegWit v0 PSBTs must include their previous transactions (blocking the BIP-143 fee attack), with a "Sign Anyway" override for coordinators that leave them out
- Output Ownership Check: Change and self-transfer outputs are proven to be yours before you sign; an output whose derivation data claims your wallet but pays elsewhere is flagged NOT YOURS (multisig signing is refused)
- Transaction Finalization: Finalize fully-signed PSBTs into broadcastable transactions
- QR Code Air-Gap: Scan PSBT → Verify → Sign → Export via QR
- Animated QR Support: BC-UR (v1/v2) and BBQr formats for large transactions
- Address Verification: Confirm receive/change addresses on trusted screen
- XPUB Export: Generate watch-only wallets on your online device
- Descriptor Import: Import multi-sig wallets via QR (BC-UR v2, BBQr) or text:
sortedmulti()and unsortedmulti()descriptors, BSMS, and ColdCard multisig setup files, with BIP-380 checksum validation - Cosigner Export: Share your signer info for multi-sig setup as a BIP-48 key expression (
[fingerprint/48h/…]xpub) - Coordinator Export: Export account keys to Nunchuk or as Coldcard/Sparrow JSON, across multiple accounts, as an animated QR
- Flexible Derivation: Supports BIP-48 m/48'/0'/0'/2' and m/48'/0'/0'/1' paths
- Sign Messages: Sign messages to prove ownership, in Electrum, BIP-137 or BIP-322 format
- Verify Signatures: Verify signatures and messages, with the signature format detected automatically
- QR Code Support: Sign Sparrow
signmessageQR requests and BIP-322 message PSBTs, and display signatures via QR codes
┌──────────────────┐ QR Code ┌──────────────────┐
│ ONLINE DEVICE │◄─────────────────────────►│ METROVAULT │
│ (Watch-Only) │ │ (Air-Gapped) │
├──────────────────┤ ├──────────────────┤
│ • Create PSBT │ ──── Unsigned PSBT ───► │ • Verify details │
│ • Broadcast TX │ ◄──── Signed PSBT ──── │ • Sign with key │
│ • View balance │ │ • Never online │
└──────────────────┘ └──────────────────┘
- Setup: Import your XPUB from MetroVault to create a watch-only wallet on your online device
- Receive: Generate addresses on either device (they'll match!)
- Send: Create unsigned transaction (PSBT) on online device → Display as QR
- Sign: Scan QR on MetroVault → Verify → Sign → Display signed PSBT QR
- Broadcast: Scan signed QR on online device → Broadcast to network
| Category | Technology |
|---|---|
| UI Framework | Jetpack Compose (Material 3) |
| Architecture | MVVM with Clean Architecture |
| Cryptography | vaultovich — Kotlin Bitcoin library (BIP-32, BIP-39, BIP-48, BIP-137, BIP-174, BIP-322, BIP-340/341/342, BIP-352, BIP-370, BIP-371, BIP-374, BIP-380) + secp256k1-kmp JNI binding |
| Storage | EncryptedSharedPreferences (Android Keystore) |
| QR Codes | ZXing + bcur-kotlin & bbqr-kotlin (Kotlin ports for BC-UR and BBQr animated multi-frame QR) |
| Biometrics | AndroidX Biometric Library (BIOMETRIC_STRONG) |
| Min SDK | Android 8.0 (API 26) |
All Bitcoin primitives — key derivation, address generation, transaction and PSBT parsing, signing (ECDSA and Schnorr), descriptors, MuSig2 and silent payments — live in vaultovich, a fork of ACINQ's bitcoin-kmp that I maintain. It started life inside this repository and was extracted into its own project so it can be audited, tested and versioned independently. MetroVault consumes it from Maven Central as com.gorunjinian:vaultovich.
The library is pure Kotlin/JVM with no networking, no persistence and no Android dependencies. It parses, derives, signs and serialises — nothing else. The only native code involved is the secp256k1-kmp JNI binding that MetroVault supplies for Android.
MetroVault itself contains the app layer: encrypted storage, session management, QR transport, multisig and silent-payment services, and the UI.
MetroVault is on F-Droid with reproducible builds — F-Droid independently rebuilds the app from this source, verifies it byte-for-byte against the release, and publishes it signed with the developer's key. To verify an installed APK:
- Package ID:
com.gorunjinian.metrovault - Signing certificate SHA-256:
1245554ceb17cea21e9912af7bf60d38d716f5884d4b3664e5338462cc76fd03
Prerequisites:
- Android Studio 2026.1 or newer (the build uses AGP 9.3)
- JDK 21 to run Gradle (downloaded automatically if missing; the app itself targets Java 17)
- Android device (API 26+)
Steps:
# Clone the repository
git clone https://github.com/gorunjinian/MetroVault.git
cd MetroVault
# Debug build (no signing key needed)
./gradlew assembleDebug
# Release build (needs a signing key in keystore.properties or environment variables, see app/build.gradle.kts)
./gradlew assembleReleaseYou can also open the project in Android Studio and build from there. The APK lands in app/build/outputs/apk/; the Device Setup Guide covers sideloading it onto your air-gapped device.
Check the Releases page for pre-built, signed APKs.
OpenAPK mirrors the release APK. Before installing, verify it matches the official build:
- Package ID:
com.gorunjinian.metrovault - Signing certificate SHA-256:
1245554ceb17cea21e9912af7bf60d38d716f5884d4b3664e5338462cc76fd03
⚠️ Security Note: For production use, install on a factory-reset device that remains permanently offline, and only install an APK you can trust: build it from source yourself, or check that its signing certificate matches the one above.
For maximum security, use a dedicated device:
1. Remove SIM card
2. Factory reset before installation
3. Skip Google account setup (offline only)
4. Enable Airplane mode permanently
5. Disable WiFi, Bluetooth, NFC, Mobile data
6. Disable USB debugging
📱 New to this? Follow the Device Setup Guide — a full step-by-step tutorial covering every step above, from factory reset to your first wallet, including how to verify and sideload the APK onto a device that never goes online.
Optional (recommended) — debloat first: before sideloading MetroVault, consider running android-debloater, a companion bash script that uses adb to uninstall bloatware and pre-installed network-reaching apps on a fresh device. After debloating, disable USB debugging.
Detailed documentation is available in the repository:
| Document | Description |
|---|---|
| DEVICE_SETUP.md | Step-by-step tutorial for preparing a dedicated air-gapped device |
| SECURITY.md | Complete security architecture and encryption model |
| SEED_GENERATION.md | How wallets are generated, stored, and used |
| FDROID_BUILD.md | How the F-Droid release is built, including secp256k1 from source and the reproducible-build setup |
| ADDRESSES.md | Canonical donation addresses, to check against metrovault.app/donate |
Contributions are welcome! Please feel free to submit issues and pull requests.
- Bugs: Open a GitHub issue with reproduction steps
- Features: Open a discussion or issue with your proposal
- Security: See SECURITY.md for responsible disclosure
MetroVault is free software, licensed under the GNU General Public License v3.0 or later (GPL-3.0-or-later). You are free to use, study, share, and modify it; any distributed derivative must remain free software under the same license. See LICENSE.txt for the full text.
The companion libraries are separate works under their own licenses: the Bitcoin library vaultovich is Apache License 2.0 (as is the upstream bitcoin-kmp it forks), and the QR libraries bbqr-kotlin and bcur-kotlin are MIT License.
- Bitcoin - The protocol that makes this all possible
- vaultovich - Our Bitcoin library, forked from ACINQ's bitcoin-kmp
- ACINQ - For bitcoin-kmp and the secp256k1-kmp bindings that vaultovich builds on
- Jetpack Compose - Modern Android UI toolkit
- ZXing - QR code generation and scanning
- The open-source Bitcoin community for BIP standards
MetroVault is currently in active development.
While every effort is made to ensure security and correctness, using early-development software for managing real funds carries risks:
- Always verify addresses on the device screen
- Test with small amounts first
- You are responsible for your own keys - ensure proper mnemonic backups
- Review the code yourself or have it audited before trusting with significant funds
Made with ❤️ for Bitcoin by Gorun Jinian










