Biometrically Authenticated Data Encryption and Decryption in Flutter β¨π
Mobile applications often deal with sensitive data that requires robust security measures. Biometric authentication, such as fingerprint or face unlock, has become a popular method to enhance security while providing a seamless user experience. In this blog post, we will explore how to implement biometrically authenticated data encryption and decryption in Flutter. π
Requirements and Dependencies ππ§
To get started, make the following changes in MainActivity.kt
If you are using FlutterActivity
directly, change it to FlutterFragmentActivity
import io.flutter.embedding.android.FlutterFragmentActivity;
class MainActivity: FlutterFragmentActivity() {
}
Permissions ππ»
Update your projectβs AndroidManifest.xml
file to include the USE_BIOMETRIC
permissions:
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.example.app">
<uses-permission android:name="android.permission.USE_BIOMETRIC"/>
<manifest>
The local_auth plugin will build and run on SDK 16+, but isDeviceSupported() will always return false before SDK 23 (Android 6.0). Make sure to change the minSdkVersion to 23 in the app levelbuild.gradle
file:
minSdkVersion 23
Make sure you have the following dependencies added to your Flutter projectβs pubspec.yaml
file:
dependencies:
flutter:
sdk: flutter
local_auth: ^2.1.6
flutter_secure_storage: ^8.0.0
encrypt: ^5.0.1
Understanding Biometric Authentication and Data Encryption π€π
Biometric authentication is a secure way to verify a userβs identity using their unique biological traits, such as fingerprints or facial features. On the other hand, data encryption involves converting sensitive information into unreadable cipher text, which can only be decrypted with a specific cryptographic key. π§¬π
Biometric Authentication with local_auth
π€π
The local_auth
the package allows us to authenticate the user using biometrics on their device. Let's integrate it into our Flutter app:
import 'package:flutter/material.dart';
import 'package:local_auth/local_auth.dart';
import 'package:flutter_secure_storage/flutter_secure_storage.dart';
import 'dart:convert';
import 'dart:typed_data';
import 'package:encrypt/encrypt.dart';
final LocalAuthentication auth = LocalAuthentication();
final FlutterSecureStorage secureStorage = FlutterSecureStorage();
Future<void> main() async {
final int keyLength = 32;
try {
// Step 1: Biometric Authentication
bool authenticated = await auth.authenticate(
localizedReason: 'Let OS determine authentication method',
options: const AuthenticationOptions(
stickyAuth: true,
),
);
if (authenticated) {
// Step 2: Generate the Cryptographic Key
final Uint8List cryptographicKey = generateCryptographicKey(keyLength);
// Step 3: Store the Cryptographic Key in Secure Storage
await secureStorage.write(key: 'cryptographic_key', value: base64.encode(cryptographicKey));
// Step 4: Encrypt and Store Data (Not covered in this blog)
// Step 5: Use the Cryptographic Key to Decrypt Data (Not covered in this blog)
}
} catch (e) {
print('Authentication failed: $e');
}
}
we perform biometric authentication using local_auth
. If the user is successfully authenticated, we generate a cryptographic key and store it securely using FlutterSecureStorage
. π±π
Generating a Cryptographic Key ππ’
A cryptographic key is essential for data encryption and decryption. Letβs start by creating a function to generate a secure cryptographic key:
import 'dart:typed_data';
import 'package:random/random.dart';
Uint8List generateCryptographicKey(int keyLength) {
final random = Random.secure();
final key = Uint8List(keyLength);
for (int i = 0; i < key.length; i++) {
key[i] = random.nextInt(256);
}
return key;
}
In this function, we use the random
package to generate a sequence of random bytes, which form the cryptographic key. π²π
Encryption and Decryption Functions ππ
To achieve secure data encryption and decryption, we need two functions: encryptAndStoreData
and decryptData
.
encryptAndStoreData
import 'package:encrypt/encrypt.dart';
import 'package:flutter_secure_storage/flutter_secure_storage.dart';
import 'dart:convert';
final FlutterSecureStorage secureStorage = FlutterSecureStorage();
Future<void> encryptAndStoreData(String data, Uint8List cryptographicKey) async {
final key = Key(cryptographicKey);
final iv = IV.fromLength(16);
final encrypter = Encrypter(AES(key));
final encryptedData = encrypter.encrypt(data, iv: iv);
await secureStorage.write(key: 'encrypted_data_key', value: encryptedData.base64);
}
The encryptAndStoreData
function takes the sensitive data
and the cryptographicKey
as input. It uses the encrypt
package to perform AES encryption with the provided key and initialization vector (IV). The encrypted data is then stored securely using FlutterSecureStorage
. ππ
decryptData
Future<String> decryptData(Uint8List cryptographicKey) async {
final String? encryptedData = await secureStorage.read(key: 'encrypted_data_key');
if (encryptedData == null) {
throw Exception('Encrypted data not found.');
}
final key = Key(cryptographicKey);
final iv = IV.fromLength(16);
final encrypter = Encrypter(AES(key));
final encrypted = Encrypted.fromBase64(encryptedData);
final decrypted = encrypter.decrypt(encrypted, iv: iv);
return decrypted;
}
The decryptData
function retrieves the encrypted data from FlutterSecureStorage
, and then decrypts it using the cryptographicKey
provided as input. It follows the same AES decryption process with the key and IV to retrieve the original sensitive data. ππ
Security β Android Keystore π‘οΈ
For Android devices, the cryptographic key generated during biometric authentication is securely stored in the Android Keystore. The Android Keystore is a secure system-wide storage for cryptographic keys and certificates, making it extremely difficult for other applications to access the keys. This ensures the highest level of security for the cryptographic key used in data encryption and decryption. π€π
Conclusion ππ
In this blog post, we explored how to implement biometrically authenticated data encryption and decryption in Flutter. By integrating biometric authentication and secure storage of cryptographic keys, we can ensure that sensitive data remains protected even if the device falls into the wrong hands. Remember to handle data encryption and decryption with care, follow security best practices, and regularly update your appβs security measures to stay ahead of potential threats. π©βπ»π¨βπ»
With the steps outlined in this blog, you can create a secure and user-friendly experience for your users while safeguarding their sensitive data. Happy coding! ππ»
You can check-out the full source code here: https://github.com/rkmonarch/flutter-biometric-encryption