flutter_biometric_crypto 0.1.4
flutter_biometric_crypto: ^0.1.4 copied to clipboard
A Flutter package for biometric-protected encryption of small secrets using Android Keystore and iOS Keychain/Secure Enclave.
flutter_biometric_crypto #
Enterprise-grade biometric-protected encryption for Flutter apps
Protect your app's sensitive data with hardware-backed security. flutter_biometric_crypto provides a simple, secure way to encrypt small secrets (like API keys, tokens, or passwords) using your device's biometric authentication and secure hardware storage.
β¨ Why Choose This Package? #
In today's security-conscious world, protecting user data is paramount. This package bridges the gap between convenience and security.
Key Features #
- π‘οΈ Hardware-Backed Security: Your private keys never leave the device's secure hardware (Android Keystore or iOS Secure Enclave).
- π Seamless User Experience: Users authenticate with their fingerprint or faceβno passwords to remember.
- π Zero-Knowledge Architecture: Even you as the developer can't access the encrypted data without user authentication.
- β‘ Production Ready: Battle-tested with comprehensive error handling and security best practices.
Perfect for storing authentication tokens, API keys, payment credentials, or any sensitive data that needs an extra layer of protection.
π Quick Start #
Installation #
Add flutter_biometric_crypto to your pubspec.yaml:
dependencies:
flutter_biometric_crypto: ^0.1.4
Then run:
flutter pub get
Basic Usage #
import 'package:flutter_biometric_crypto/flutter_biometric_crypto.dart';
import 'dart:typed_data';
// 1. Initialize the key (one-time setup)
await FlutterBiometricCrypto.initKey();
// 2. Check if biometric is available
final isAvailable = await FlutterBiometricCrypto.isBiometricAvailable();
if (!isAvailable) {
// Handle gracefully - show alternative authentication
return;
}
// 3. Encrypt your sensitive data
final sensitiveData = Uint8List.fromList('MySecretAPIKey123'.codeUnits);
final encrypted = await FlutterBiometricCrypto.encrypt(sensitiveData);
// 4. Decrypt when needed (prompts for biometric)
final decrypted = await FlutterBiometricCrypto.decrypt(encrypted);
final decryptedText = String.fromCharCodes(decrypted);
print(decryptedText); // Output: MySecretAPIKey123
That's it! Your data is now protected by biometric authentication and secure hardware storage.
π± Platform Setup #
Android #
- Set Minimum SDK Version (API 23+ required)
Add to android/app/build.gradle:
android {
defaultConfig {
minSdkVersion 23 // Android 6.0+
}
}
- Add Biometric Dependency (Included automatically, but ensure conflicts don't exist)
The plugin uses androidx.biometric:biometric:1.1.0.
- Permissions (automatically included)
The plugin automatically includes required permissions:
USE_BIOMETRICUSE_FINGERPRINT
iOS #
-
Minimum iOS Version: iOS 12.0 or higher
-
Add Face ID Usage Description
Add to ios/Runner/Info.plist:
<key>NSFaceIDUsageDescription</key>
<string>This app uses Face ID to securely authenticate and decrypt your encrypted data.</string>
- Keychain Access (automatic)
The plugin uses iOS Keychain which is available by default. For devices with Secure Enclave, keys are automatically stored there for maximum security.
π‘ Real-World Examples #
Storing an API Token #
// Encrypt and store API token
final apiToken = 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...';
final tokenBytes = Uint8List.fromList(apiToken.codeUnits);
final encryptedToken = await FlutterBiometricCrypto.encrypt(tokenBytes);
// Store encryptedToken in your app's secure storage
await secureStorage.write(key: 'api_token', value: base64Encode(encryptedToken));
// Later, retrieve and decrypt
final storedEncrypted = base64Decode(await secureStorage.read(key: 'api_token'));
final decryptedToken = await FlutterBiometricCrypto.decrypt(storedEncrypted);
final token = String.fromCharCodes(decryptedToken);
Protecting User Credentials #
// Encrypt user password before storing
final password = 'userPassword123';
final passwordBytes = Uint8List.fromList(password.codeUnits);
final encryptedPassword = await FlutterBiometricCrypto.encrypt(passwordBytes);
// Store encrypted password
// ... later decrypt when user needs to authenticate
π οΈ API Reference #
initKey() #
Generates a new RSA 2048 key pair if one doesn't exist. Safe to call multiple timesβit won't create duplicate keys.
await FlutterBiometricCrypto.initKey();
When to call: Once during app initialization or before first use.
encrypt(Uint8List data) #
Encrypts data using the public key. No authentication required.
final encrypted = await FlutterBiometricCrypto.encrypt(data);
Parameters:
data: Data to encrypt (max 1 KB / 1024 bytes)
Returns: Future<Uint8List> - Encrypted data
Throws:
DataTooLargeException- Data exceeds 1 KB limitKeyNotFoundException- Key not initialized (callinitKey()first)EncryptionException- Encryption operation failed
decrypt(Uint8List encrypted) #
Decrypts data using the private key. Requires biometric authentication.
final decrypted = await FlutterBiometricCrypto.decrypt(encrypted);
Parameters:
encrypted: Previously encrypted data
Returns: Future<Uint8List> - Decrypted data
Throws:
BiometricNotAvailableException- No biometric sensor or not enrolledBiometricAuthenticationFailedException- User failed or cancelled authenticationKeyNotFoundException- Key not initializedDecryptionException- Decryption operation failed
isBiometricAvailable() #
Checks if biometric authentication is available and properly configured.
final available = await FlutterBiometricCrypto.isBiometricAvailable();
if (available) {
// Proceed with biometric-protected operations
}
Returns: Future<bool> - true if biometric is ready to use
deleteKey() #
Permanently removes the key pair from secure storage. Use with caution!
await FlutterBiometricCrypto.deleteKey();
Note: After deletion, you'll need to call initKey() again before encrypting/decrypting.
β οΈ Error Handling #
Always handle exceptions gracefully:
try {
final encrypted = await FlutterBiometricCrypto.encrypt(data);
// Success!
} on DataTooLargeException catch (e) {
// Data is too large - consider splitting or using hybrid encryption
print('Error: ${e.message}');
} on KeyNotFoundException catch (e) {
// Initialize key first
await FlutterBiometricCrypto.initKey();
// Retry encryption
} on EncryptionException catch (e) {
// Handle encryption failure
print('Encryption failed: ${e.message}');
}
try {
final decrypted = await FlutterBiometricCrypto.decrypt(encrypted);
// Success!
} on BiometricNotAvailableException catch (e) {
// No biometric available - show alternative authentication method
showAlternativeAuth();
} on BiometricAuthenticationFailedException catch (e) {
// User failed authentication or cancelled
showError('Authentication failed. Please try again.');
} on DecryptionException catch (e) {
// Handle decryption failure
print('Decryption failed: ${e.message}');
}
π Security Best Practices #
-
Always Check Biometric Availability
if (!await FlutterBiometricCrypto.isBiometricAvailable()) { // Provide fallback authentication method } -
Handle Errors Securely
- Never log sensitive data or encryption keys
- Don't expose error details to end users
- Log errors for debugging but sanitize sensitive information
-
Key Management
- Call
initKey()during app initialization - Only delete keys when user explicitly requests account deletion
- Never extract or share private keys
- Call
-
Data Size Considerations
- Maximum 1 KB per encryption operation
- For larger data, use hybrid encryption:
- Generate a symmetric key (AES)
- Encrypt the symmetric key with this package
- Encrypt your data with the symmetric key
π Limitations & Considerations #
Data Size Limit #
Maximum: 1 KB (1024 bytes) per encryption operation.
Why? RSA encryption is designed for small data. For larger payloads, use hybrid encryption (encrypt a symmetric key with this package, then use AES for your data).
Platform Support #
- β Android: API 23+ (Android 6.0+)
- β iOS: 12.0+
- β Web, macOS, Windows, Linux (not supported)
Biometric Requirements #
- Android: Requires fingerprint sensor or face unlock
- iOS: Requires Face ID or Touch ID enrollment
- Fallback: iOS may fall back to device passcode if biometric fails
Key Persistence #
Keys are stored in platform-specific secure storage:
- Lost if: App is uninstalled or app data is cleared
- Persists: Across app updates and device restarts
- Not synced: Keys are device-specific and never leave the device
π§ͺ Testing #
Unit Tests #
flutter test
Integration Tests #
Requires a real device or emulator with biometric support:
flutter test integration_test/flutter_biometric_crypto_test.dart
Note:
- Android emulators: Configure fingerprint in Settings > Security
- iOS simulators: Use Hardware > Face ID > Enrolled
π± Example App #
A complete example app demonstrating all features is available in the example/ directory.
cd example
flutter run
The example app includes:
- Key initialization
- Biometric availability checking
- Encryption/decryption workflow
- Error handling examples
- UI for testing all features
π Troubleshooting #
"Biometric not available" on Android #
- β Ensure device has fingerprint sensor or face unlock
- β Set up biometric authentication in device Settings
- β
Verify
minSdkVersionis 23 or higher - β
Check that
androidx.biometric:biometric:1.1.0is in dependencies
"Biometric not available" on iOS #
- β Ensure Face ID or Touch ID is set up on device
- β
Verify
NSFaceIDUsageDescriptionis inInfo.plist - β Check app entitlements in Xcode
"Key not found" error #
- β
Call
initKey()before first use - β Ensure app has proper permissions
- β On Android, verify device supports Android Keystore
Decryption fails immediately #
- β
Check
isBiometricAvailable()first - β Ensure user has enrolled biometrics
- β Verify key was initialized successfully
π¨βπ» Author #
Godfrey Lebo - Fullstack Developer & Technical PM
With 9+ years of industry experience, I specialize in building AI-powered applications, scalable mobile solutions, and secure backend systems. I've led teams delivering marketplaces, fintech platforms, and AI applications serving thousands of users.
- π§ Email: emorylebo@gmail.com
- πΌ LinkedIn: godfreylebo
- π Portfolio: godfreylebo.dev
- π GitHub: @emorilebo
π€ Contributing #
Contributions are welcome! Whether it's:
- π Bug reports
- π‘ Feature suggestions
- π Documentation improvements
- π§ Code contributions
Please feel free to open an issue or submit a pull request.
π License #
This project is licensed under the MIT License - see the LICENSE file for details.
π Additional Resources #
- CHANGELOG.md - Version history and updates
- GitHub Repository - Source code and issues
Made with β€οΈ by Godfrey Lebo
If this package helps secure your app, consider giving it a β on GitHub!