Generate key pairs and cryptographic signatures using NIST P-256 EC key pair with ECDSA, protected by biometric authentication for Flutter (Android & iOS).
- π Secure Key Generation - Generate NIST P-256 EC key pairs
- π Biometric Protection - Keys protected by fingerprint or Face ID
- βοΈ Digital Signatures - Create and verify ECDSA signatures
- π± Cross-Platform - Works on both Android and iOS
- π Biometric Change Detection - Detect when biometric data changes
- πΎ Secure Storage - Keys stored securely in platform keystore
Add to your pubspec.yaml:
dependencies:
local_auth_signature: ^1.0.12Then run:
flutter pub getimport 'package:local_auth_signature/local_auth_signature.dart';final _localAuthSignature = LocalAuthSignature.instance;
final _key = 'com.yourapp.signatureKey';try {
final publicKey = await _localAuthSignature.createKeyPair(
_key,
AndroidPromptInfo(
title: 'BIOMETRIC',
subtitle: 'Please allow biometric',
negativeButton: 'CANCEL',
),
IOSPromptInfo(reason: 'Please allow biometric'),
);
print('Public Key: $publicKey');
} on PlatformException catch (e) {
print('Error: ${e.code}');
}- Update
MainActivity.kt:
import io.flutter.embedding.android.FlutterFragmentActivity
class MainActivity : FlutterFragmentActivity()- Add permissions to
AndroidManifest.xml:
<uses-permission android:name="android.permission.USE_BIOMETRIC" />- Add JitPack repository to
build.gradle:
buildscript {
repositories {
maven { url "https://jitpack.io" }
}
}
allprojects {
repositories {
maven { url "https://jitpack.io" }
}
}Add to your Info.plist:
<dict>
<key>NSFaceIDUsageDescription</key>
<string>This application wants to access your TouchID or FaceID</string>
</dict>final bool hasChanged = await _localAuthSignature.isBiometricChanged(_key);await _localAuthSignature.resetBiometricChanged();final String publicKey = await _localAuthSignature.createKeyPair(
keyName,
androidPrompt,
iosPrompt,
);final String signature = await _localAuthSignature.sign(
keyName,
payload,
androidPrompt,
iosPrompt,
);final bool isValid = await _localAuthSignature.verify(
keyName,
payload,
signature,
androidPrompt,
iosPrompt,
);class BiometricSignature {
final _localAuthSignature = LocalAuthSignature.instance;
final _key = 'com.yourapp.biometric.key';
final _payload = 'Hello, World!';
Future<void> demonstrateSignature() async {
try {
// Check if biometrics changed
final changed = await _localAuthSignature.isBiometricChanged(_key);
if (changed) {
// Handle biometric enrollment changes
print('Biometrics have changed!');
}
// Create key pair
final publicKey = await _localAuthSignature.createKeyPair(
_key,
AndroidPromptInfo(
title: 'Create Key',
subtitle: 'Authenticate to create secure key',
negativeButton: 'Cancel',
),
IOSPromptInfo(reason: 'Authenticate to create secure key'),
);
print('Public Key: $publicKey');
// Sign data
final signature = await _localAuthSignature.sign(
_key,
_payload,
AndroidPromptInfo(
title: 'Sign Data',
subtitle: 'Authenticate to sign',
negativeButton: 'Cancel',
),
IOSPromptInfo(reason: 'Authenticate to sign'),
);
print('Signature: $signature');
// Verify signature
final verified = await _localAuthSignature.verify(
_key,
_payload,
signature,
AndroidPromptInfo(
title: 'Verify Signature',
subtitle: 'Authenticate to verify',
negativeButton: 'Cancel',
),
IOSPromptInfo(reason: 'Authenticate to verify'),
);
print('Verified: $verified');
} on PlatformException catch (e) {
handleError(e);
}
}
void handleError(PlatformException e) {
switch (e.code) {
case 'auth_failed':
print('Authentication failed');
break;
case 'not_available':
print('Biometric authentication not available');
break;
case 'user_cancel':
print('User cancelled authentication');
break;
default:
print('Error: ${e.code} - ${e.message}');
}
}
}Common error codes:
| Code | Description |
|---|---|
auth_failed |
Authentication failed |
not_available |
Biometric authentication not available |
user_cancel |
User cancelled authentication |
key_not_found |
Key not found in keystore |
biometric_changed |
Biometric enrollment has changed |
- Key Storage: Private keys are stored in platform-specific secure storage
- Biometric Protection: Keys require biometric authentication to use
- Change Detection: Keys become invalid when biometric data changes
- Platform Security: Leverages Android Keystore and iOS Secure Enclave
Contributions are welcome! Please feel free to submit a Pull Request.
This project is licensed under the MIT License - see the LICENSE file for details.
If you find this package helpful, please consider supporting it:

