native_encrypted_storage 0.1.0
native_encrypted_storage: ^0.1.0 copied to clipboard
Secure storage with native encryption using Android Keystore. All encryption happens in native code for maximum security. iOS support coming soon.
Native Encrypted Storage #
A Flutter plugin for secure data storage with hardware-backed encryption using Android Keystore. All encryption happens in native code for maximum security.
Note: Currently supports Android only. iOS support is coming in a future update.
π Features #
- β AES-256-GCM Encryption - Military-grade encryption
- β Hardware-Backed Security - Keys stored in Android Keystore
- β Native Implementation - All encryption happens in native code (Kotlin)
- β Simple API - Easy to use, similar to SharedPreferences
- β No External Dependencies - Uses only Android native APIs
- β Production Ready - Clean code without debug logs
- π iOS Support - Coming in a future update
π Why Use This Plugin? #
The Problem with JWT and Other Tokens #
JWT tokens and API keys are often stored in plain text or with Base64 encoding, which is NOT encryption:
// β INSECURE - Anyone with file access can read this
final prefs = await SharedPreferences.getInstance();
await prefs.setString('token', jwtToken);
Even though JWT is signed, the payload is readable by anyone:
eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VyIjoiam9obiJ9.signature
β This is just Base64 - easily decoded!
The Solution #
// β
SECURE - Encrypted with AES-256, key stored in hardware
await storage.write(key: 'token', value: jwtToken);
The token is now encrypted and impossible to read without the encryption key from Keystore/Keychain.
π¦ Installation #
Add this to your pubspec.yaml:
dependencies:
native_encrypted_storage: ^0.1.0
Then run:
flutter pub get
π― Usage #
Basic Example #
import 'package:native_encrypted_storage/native_encrypted_storage.dart';
final storage = NativeEncryptedStorage();
// Save encrypted data
await storage.write(
key: 'user_token',
value: 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...',
);
// Read and decrypt data
final token = await storage.read(key: 'user_token');
print(token); // Original value, automatically decrypted
// Delete data
await storage.delete(key: 'user_token');
// Delete all data
await storage.deleteAll();
// Check if key exists
final exists = await storage.containsKey(key: 'user_token');
// Get all keys
final keys = await storage.getAllKeys();
Real-World Example: Authentication #
class AuthService {
final _storage = NativeEncryptedStorage();
// Save user token after login
Future<void> saveToken(String token) async {
await _storage.write(key: 'auth_token', value: token);
}
// Get token for API requests
Future<String?> getToken() async {
return await _storage.read(key: 'auth_token');
}
// Save user credentials (if needed)
Future<void> saveCredentials({
required String email,
required String password,
}) async {
await _storage.write(key: 'user_email', value: email);
await _storage.write(key: 'user_password', value: password);
}
// Logout - clear all data
Future<void> logout() async {
await _storage.deleteAll();
}
}
π How It Works #
Architecture #
βββββββββββββββββββββββββββββββββββββββββββ
β Your Flutter App β
β storage.write(key, value) β
βββββββββββββββββββ¬ββββββββββββββββββββββββ
β
βββββββββββββββββββββββββββββββββββββββββββ
β Native Code (Kotlin) β
β 1. Get encryption key from Keystore β
β 2. Encrypt value with AES-256-GCM β
β 3. Save encrypted data β
ββββββββββββ¬βββββββββββββββ¬ββββββββββββββββ
β β
ββββββββββββ βββββββββββββββ
β Keystore β βSharedPrefs β
β π β β key β π¦ β
ββββββββββββ βββββββββββββββ
Hardware-backed Encrypted data
What Gets Encrypted? #
| Item | Encrypted? | Location | Purpose |
|---|---|---|---|
| Encryption Key | β Hardware-protected | Android Keystore | Encrypts/decrypts data |
| Key (identifier) | β Plain text | SharedPreferences | Used to find data |
| Value (your data) | β AES-256-GCM | SharedPreferences | Your sensitive data |
Security Details #
- Algorithm: AES-256-GCM (Galois/Counter Mode)
- Key Size: 256 bits
- IV: Random 12 bytes per encryption
- Authentication: 128-bit authentication tag
- Key Storage: Android Keystore (hardware-backed) / iOS Keychain
π‘οΈ Security Guarantees #
β What This Plugin Protects Against #
- File Access: Even if someone gets your app's data files, they cannot decrypt the data
- Backup Extraction: Encrypted data in backups is useless without the hardware key
- Rooted/Jailbroken Devices: Keys are hardware-protected and cannot be extracted
- Memory Dumps: Data is encrypted at rest, only decrypted when needed
β οΈ What This Plugin Does NOT Protect Against #
- Runtime Access: If malware is running in your app's process, it can read decrypted data
- Screen Recording: Decrypted data shown on screen can be captured
- Debugger Attachment: A debugger can read decrypted values in memory
π± Platform Support #
| Platform | Status | Minimum Version | Encryption Backend |
|---|---|---|---|
| Android | β Supported | API 23 (6.0) | Android Keystore |
| iOS | π Coming Soon | - | - |
π§ API Reference #
Methods #
write({required String key, required String value})
Encrypts and saves a value.
await storage.write(key: 'api_key', value: 'secret123');
read({required String key})
Reads and decrypts a value. Returns null if key doesn't exist.
final value = await storage.read(key: 'api_key');
delete({required String key})
Deletes a key-value pair.
await storage.delete(key: 'api_key');
deleteAll()
Deletes all stored data.
await storage.deleteAll();
containsKey({required String key})
Checks if a key exists.
final exists = await storage.containsKey(key: 'api_key');
getAllKeys()
Returns all stored keys.
final keys = await storage.getAllKeys();
π Comparison with Other Solutions #
| Feature | Native Encrypted Storage | flutter_secure_storage | SharedPreferences | Hive (encrypted) |
|---|---|---|---|---|
| Hardware-backed | β Yes | β Yes | β No | β No |
| Encryption | β AES-256-GCM | β AES-CBC | β None | β AES-256 |
| Native Code | β Yes | β Yes | β Yes | β Dart only |
| Key Storage | β Keystore/Keychain | β Keystore/Keychain | β Plain text | β In app |
| Performance | β‘ Fast | β‘ Fast | β‘ Very Fast | β‘ Very Fast |
| Setup | β Zero config | β οΈ Requires config | β Zero config | β οΈ Manual key |
π‘ Best Practices #
β DO #
- Use for sensitive data (tokens, passwords, API keys)
- Use unique, descriptive keys
- Handle exceptions properly
- Clear data on logout
try {
await storage.write(key: 'token', value: token);
} catch (e) {
print('Failed to save token: $e');
}
β DON'T #
- Store large files (use encrypted file storage instead)
- Store non-sensitive data (use SharedPreferences for better performance)
- Use the same key for different data types
- Forget to handle null returns from
read()
π Troubleshooting #
Android: "Key not found" after app reinstall #
This is expected behavior. The encryption key is tied to the app installation. When you uninstall and reinstall, the old encrypted data cannot be decrypted.
Solution: Clear data on first launch after reinstall.
Android: Encryption fails #
Check that your minimum SDK version is met:
- Android: minSdkVersion 23 (Android 6.0)
iOS Support #
iOS support is coming in a future update. Stay tuned!
π License #
MIT License - see LICENSE file for details.
π€ Contributing #
Contributions are welcome! Please feel free to submit a Pull Request.
π§ Support #
For issues and feature requests, please use the GitHub issue tracker.
π Acknowledgments #
- Android Keystore documentation
- iOS Keychain Services documentation
- Flutter plugin development guide
Made with β€οΈ for secure Flutter apps