feat(rn_cli_wallet): encrypt MMKV secret storage with keychain-backed key#566
Draft
ignaciosantise wants to merge 1 commit into
Draft
feat(rn_cli_wallet): encrypt MMKV secret storage with keychain-backed key#566ignaciosantise wants to merge 1 commit into
ignaciosantise wants to merge 1 commit into
Conversation
… key Wallet mnemonics/private keys were persisted as plaintext in MMKV. Encrypt the MMKV store at rest on native using MMKV's built-in encryptionKey, with a random key generated once and kept in the iOS Keychain / Android Keystore via expo-secure-store. All secret access is funneled through a single chokepoint (getEncryptionKey), so every chain is protected at once and the design is ready for optional biometric gating later. - add expo-secure-store dependency - new src/utils/secureEncryptionKey.ts owns the key lifecycle (native-only; web returns undefined and stays best-effort/unencrypted by design) - storage.ts lazily opens an encrypted MMKV; on first run it recrypts the existing plaintext store in place so wallets aren't reset on upgrade - reword now-inaccurate "stored unencrypted" dev warnings in the chain utils Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
|
Claude finished @ignaciosantise's task in 2m 33s —— View job Code Review in Progress
|
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.

Problem
wallets/rn_cli_walletpersisted every chain's mnemonic / private key / secret key as plaintext in MMKV (new MMKV()with noencryptionKey). Anyone with filesystem or backup access to the device could read the seed phrases. The code itself warned about this ([SECURITY] … stored unencrypted).Fix
Encrypt the whole MMKV store at rest on native using MMKV's built-in
encryptionKey, with a random key generated once and kept in the iOS Keychain / Android Keystore viaexpo-secure-store. The key that protects the secrets never sits in plaintext.Chosen deliberately over moving secrets into SecureStore per-chain: all secret access is funneled through a single chokepoint (
getEncryptionKey), so every chain is protected at once, the 7 copy-pasted-from-web chain utils stay untouched, and it leaves a clean seam for optional biometric gating later.Changes
package.json/yarn.lock— addexpo-secure-store@~56.0.4(matches the SDK-56 unified versioning track).src/utils/secureEncryptionKey.ts(new) — owns the encryption-key lifecycle. Native-only; generates a 16-char key (8 random bytes hex, respecting MMKV's ≤16-byte limit) via the globalcrypto.getRandomValues, stores it in SecureStore, and memoizes. Web returnsundefined(no native secure storage in a browser).src/utils/storage.ts— MMKV is now opened lazily (the key fetch is async; thestorage.*methods were already async so signatures are unchanged). On first run it recrypts the existing plaintext store in place so wallets aren't reset on upgrade; afterwards it opens withencryptionKey. Dev-onlyconsole.logs report which path ran.stored unencrypteddev warnings.Platform behavior
localStorageshim, unencrypted by design (documented limitation).How to verify
cd wallets/rn_cli_wallet && yarn install, rebuild, clear Metro/gradle caches (encryption changes the on-disk format).MMKV recrypted in place …(first run) thenMMKV opened ENCRYPTED …on subsequent launches.Notes
requireAuthentication: trueinsecureEncryptionKey.ts+ theexpo-secure-storeconfig plugin forNSFaceIDUsageDescription.node_modulesnot installed here) — verification above is the intended path.🤖 Generated with Claude Code