react-native-secure-async-storage
v1.0.3
Published
AES-256-GCM secure storage via Android Keystore and iOS Keychain + CryptoKit. Keys never leave native code.
Maintainers
Readme
react-native-secure-storage-native
AES-256-GCM encrypted key–value storage for React Native using native cryptography only (no JavaScript crypto). The encryption key never leaves the Android Keystore or iOS Keychain.
Features
- AsyncStorage-like API:
setItem,getItem,removeItem,clear,multiSet,exist - Android: AES/GCM/NoPadding, key in Android Keystore, IV + ciphertext stored as Base64 in
SharedPreferences - iOS: CryptoKit AES-GCM, single symmetric key in Keychain, combined nonce + ciphertext + tag stored as Base64 in app-scoped
UserDefaults - Promise-based native module (
SecureStorage), compatible with React Native autolinking
Installation
npm install react-native-secure-storage-nativeiOS:
cd ios && pod install && cd ..Rebuild your app (native code changed).
Usage
import {
setItem,
getItem,
removeItem,
clear,
multiSet,
exist,
SecureStorage,
} from 'react-native-secure-storage-native';
await setItem('token', 'secret-value');
const value = await getItem('token'); // string | null
await exist('token'); // boolean
await multiSet([
['a', '1'],
['b', '2'],
]);
await removeItem('token');
await clear();Error handling
- Invalid or empty keys are rejected in the TypeScript layer before calling native code.
- Android: failed decrypts reject with code
E_SECURE_STORAGE_DECRYPT(corrupted data, tampering, or key mismatch). - iOS: same code on decrypt failure; invalid Base64 or CryptoKit failures surface as
E_SECURE_STORAGEorE_SECURE_STORAGE_DECRYPT.
Wrap calls in try/catch for production flows.
Security notes
- Plaintext and keys are not exposed to JavaScript; only ciphertext strings are stored in native preferences.
- GCM provides confidentiality and authenticity (detects tampering).
- A new IV/nonce is used for every encryption on Android; iOS CryptoKit generates a fresh nonce per seal.
- Android: the AES key is non-extractable from Keystore under normal device policy.
- iOS: the key lives in the Keychain with
kSecAttrAccessibleAfterFirstUnlockThisDeviceOnly. - Threat model: this protects data at rest on the device from casual inspection and many app-level attacks; it does not replace server-side controls, certificate pinning, or protection against a fully compromised OS.
Platform notes
- Android: The library uses the Gradle
namespace/ Java packagecom.rnsecurestoragenativeso it does not clash with other libraries that shipcom.securestorage(which would duplicateBuildConfigand break DEX merging). Minimum SDK 24+ recommended; Keystore behavior is device-dependent on very old or custom ROMs. - iOS: Requires iOS 13+ (CryptoKit). Encrypted values use a dedicated
UserDefaultssuite name. - Backups: If you must exclude stored values from iCloud or device backup, configure backup rules separately (not handled inside this library).
Example app
The example/ directory is a React Native app that depends on this package via "react-native-secure-storage-native": "file:..".
cd example
npm install
# iOS
export LANG=en_US.UTF-8
cd ios && pod install && cd ..
npx react-native run-ios
# Android
npx react-native run-androidIf pod install fails with a UTF-8 / Unicode error, set LANG and LC_ALL to a UTF-8 locale (as above) and retry.
When you use file:.. to depend on this library locally, run npm install in the example app after changing library files such as react-native.config.js or the podspec so node_modules picks up the latest copy.
License
MIT
