Shamir's Secret Sharing in a Mobile Wallet
A 2-of-3 Shamir threshold in React Native: device shard in Secure Enclave, auth shard on HSM, cloud recovery. How we protect private keys.
The private key problem in non-custodial wallets
If you're building a non-custodial crypto wallet, the first question is the hardest one: who controls the private key?
Store it on the server, and you're a custodian — regulated, liable, and a single point of failure. Store it only on the user's device, and one lost phone means permanent loss of funds. Give the user a seed phrase and hope they write it down correctly — we've all seen how that works in practice.
Shamir's Secret Sharing solves this by splitting the key into multiple shards, any subset of which can reconstruct the original. No single shard is useful on its own. You get non-custodial control (no one entity holds the key) with practical recovery (you don't need all shards, just enough of them).
We implemented a 2-of-3 Shamir threshold scheme in a React Native wallet running on Expo SDK 52, targeting Polygon, Base, and Arbitrum. Here's how it works in production.
2-of-3 Shamir threshold: device, HSM, cloud
The private key is split into three shards. Any two of the three are sufficient to reconstruct the key and sign a transaction. The three shards live in fundamentally different environments:
The device shard lives in the phone's hardware-backed secure enclave (iOS Secure Enclave Processor or Android Keystore). Encrypted with AES-256-GCM, protected by biometric authentication. It never leaves the secure enclave except during signing, and even then only for the duration of the computation.
The auth shard sits on our backend's Hardware Security Module (HSM). When a user wants to sign a transaction, they authenticate to the server and prove they possess the device shard (without revealing it). The server provides its partial signature. Our own engineers can't extract this shard. That's the point of an HSM.
The recovery shard is the insurance policy, optionally backed up to iCloud or Google Drive, encrypted with the user's credentials. If the phone is lost, recovery shard plus auth shard meets the 2-of-3 threshold. New device, wallet restored.
Nobody can act alone. Not us, not the user, not Apple or Google. Day-to-day transactions require the device shard (user's phone) and the auth shard (our server). We can't sign without their biometric. They can't sign without our HSM.
Secure Enclave, Android Keystore, and biometric gates
The device shard's security depends entirely on the quality of the on-device secure storage. We use the platform's highest-security option on each OS:
iOS makes this straightforward. The Secure Enclave Processor is a hardware coprocessor physically isolated from the main processor. Keys stored there can't be extracted, even by Apple, even with physical device access. We use expo-secure-store configured for the Secure Enclave, biometric required for every access. It just works.
Android is a different story. The hardware-backed Keystore provides similar guarantees on devices with a dedicated security chip, which covers most modern phones. But we discovered (the hard way) that not all Android Keystore implementations are equal. Some budget devices claim hardware backing but actually use software emulation. Our initialization flow now probes the device's security level and warns users when hardware backing isn't available. Samsung, Google Pixel, and Huawei all behave slightly differently. Fun times.
We don't offer a PIN fallback. No "remember for 5 minutes." You authenticate with your face or fingerprint every single time you sign a transaction. A stolen unlocked phone shouldn't be enough to drain a wallet, and in our design, it isn't.
Cloud recovery via iCloud and Google Drive
The recovery shard solves the lost-device scenario without introducing a custodian.
When the user enables cloud backup, the recovery shard is encrypted client-side before being uploaded to their personal iCloud or Google Drive storage. We never see the unencrypted shard. The backup file is associated with their account but stored in their own cloud space, not ours.
Recovery on a new device works like this:
- User installs the wallet on a new phone
- Authenticates to our backend (proving identity)
- Downloads and decrypts the recovery shard from cloud storage
- Combines recovery shard + auth shard (2-of-3 threshold met)
- Reconstructs the private key, generates a new device shard, stores it in the new phone's secure enclave
- Cloud backup is refreshed with the new device's recovery shard
The entire flow takes under a minute. The user never sees a seed phrase, never transcribes 24 words onto paper, never worries about a fireproof safe. The cryptographic security is stronger than seed phrases, and the UX is dramatically simpler.
We also support device-to-device transfer via QR code for users who have both the old and new phone available, and seed phrase import for users migrating from other wallets that use the BIP-39 standard.
WebAuthn passkeys and hardware-bound authentication
On top of Shamir's Secret Sharing for key management, we added WebAuthn/Passkey support for authentication. This replaces password-based login with hardware-bound credentials that are resistant to phishing, credential stuffing, and replay attacks.
A passkey is a public-private key pair where the private key lives in the device's secure hardware and cannot be exported. Authentication works by signing a challenge from the server — proving you possess the hardware-bound key without transmitting it. There's no password to steal, no OTP to intercept, no session to hijack.
The combination of passkeys (for authentication) and Shamir (for transaction signing) creates two independent security layers. Compromising one doesn't help with the other. An attacker who somehow obtained the auth shard would still need the device shard (protected by biometrics and the secure enclave) to sign a transaction.
Shamir vs MPC vs hardware wallets
There are three main approaches to non-custodial key management, each with different trade-offs:
Shamir's Secret Sharing (what we use) splits the key and reconstructs it for signing. The private key exists in memory during signature computation, which is the primary trade-off. The advantage is simplicity: the math is well-understood (Galois field arithmetic over GF(256)), the implementation is straightforward, and it's compatible with any blockchain that uses standard signature schemes.
Multi-Party Computation (MPC) generates partial signatures from each shard without ever reconstructing the full key. The key literally never exists in one place. This is theoretically more secure during signing, but the protocols are more complex, harder to audit, and typically require interactive communication between parties during signing. Latency and reliability become engineering problems.
Hardware wallets (Ledger, Trezor) store the key on a dedicated physical device. Security is excellent, but the UX is terrible for mobile: you need the hardware wallet physically present to sign. For a mobile payment wallet used daily, this is impractical.
We chose Shamir because the security-to-usability ratio is right for our use case. The key exists in memory for milliseconds during signing, protected by biometric gates and secure enclave isolation. For a mobile stablecoin wallet (not a cold storage vault), that's the appropriate trade-off. If we were building a custody solution holding institutional assets, we'd use MPC. Different threat model, different choice.
What we got wrong and what worked
Android Keystore fragmentation cost us weeks. Samsung, Google, and Huawei all implement the spec differently. Key attestation (proving to the server that a key is genuinely in hardware) works reliably on Pixel, inconsistently on Samsung, and not at all on some Chinese OEM devices. We ended up building a device capability detection layer that degrades gracefully while warning users about their security level. Not glamorous work, but necessary.
Cloud backup adoption surprised us. We designed recovery as optional, expecting security-conscious crypto users to reject it. Over 80% enable it. Turns out most people prioritize "I can recover my wallet" over "my recovery shard is offline." So much for seed phrases on paper.
What happens when biometrics change? A bandaged finger, a facial injury, new glasses that confuse face recognition. We handle it with a time-limited recovery path using the auth shard plus a re-verification flow. Took several iterations to get that UX right without accidentally creating a security backdoor.
The Shamir math itself (polynomial evaluation over GF(256)) took a few days. The platform-specific secure storage integration, the biometric flows, the cloud backup reliability across iOS and Android, the error handling for every conceivable failure mode? Months. Cryptographic algorithms are well-documented. Making them work reliably on 10,000 different Android devices is not.
The same wallet also implements zero-knowledge proofs for private transactions — because protecting the keys is only half the problem. Protecting the transaction history is the other half. And both systems operate on top of the financial infrastructure we're building in the broader FinAegis ecosystem.
If you're building a wallet, a key management system, or any application that needs to split secrets across trust boundaries — we've been through the hard parts and we're happy to talk.
Working on something similar?
We bring the same engineering approach to client projects. Tell us about yours.