fingerprint_pro 1.0.2 copy "fingerprint_pro: ^1.0.2" to clipboard
fingerprint_pro: ^1.0.2 copied to clipboard

Secure biometric authentication and keystore-based signature system for Flutter, providing both simple and advanced fingerprint/face unlock features.

example/lib/fingerprint_pro_example.dart

import 'dart:convert';
import 'dart:typed_data';
import 'package:flutter/material.dart';

// Use the mock implementation for publishing
import 'mock_fingerprint_pro.dart' as fp;

// Simple type definitions for the example
enum BiometricType {
  fingerprint,
  face,
  iris,
  strong,
  weak,
}

class BiometricResult {
  final bool success;
  final BiometricError? error;
  final String? errorMessage;

  const BiometricResult({
    required this.success,
    this.error,
    this.errorMessage,
  });

  factory BiometricResult.success() => const BiometricResult(success: true);

  factory BiometricResult.failure(BiometricError error, [String? message]) =>
      BiometricResult(success: false, error: error, errorMessage: message);
}

enum BiometricError {
  notAvailable,
  notEnrolled,
  cancelled,
  authenticationFailed,
  unsupported,
  permissionDenied,
  temporarilyUnavailable,
  permanentlyUnavailable,
  timeout,
  platformError,
  keyGenerationFailed,
  keyNotFound,
  signatureFailed,
  invalidKeySpec,
}

extension BiometricErrorExtension on BiometricError {
  String get description {
    switch (this) {
      case BiometricError.notAvailable:
        return 'Biometric authentication is not available on this device';
      case BiometricError.notEnrolled:
        return 'No biometric credentials are enrolled on this device';
      case BiometricError.cancelled:
        return 'Biometric authentication was cancelled by the user';
      case BiometricError.authenticationFailed:
        return 'Biometric authentication failed';
      case BiometricError.unsupported:
        return 'Biometric authentication is not supported on this device';
      case BiometricError.permissionDenied:
        return 'Permission denied for biometric authentication';
      case BiometricError.temporarilyUnavailable:
        return 'Biometric authentication is temporarily unavailable';
      case BiometricError.permanentlyUnavailable:
        return 'Biometric authentication is permanently unavailable';
      case BiometricError.timeout:
        return 'Biometric authentication timed out';
      case BiometricError.platformError:
        return 'A platform-specific error occurred';
      case BiometricError.keyGenerationFailed:
        return 'Failed to generate cryptographic key pair';
      case BiometricError.keyNotFound:
        return 'The specified key was not found';
      case BiometricError.signatureFailed:
        return 'Failed to create or verify signature';
      case BiometricError.invalidKeySpec:
        return 'Invalid key specification provided';
    }
  }
}

class BiometricOptions {
  final bool stickyAuth;
  final bool sensitiveTransaction;
  final String? reason;
  final String? title;
  final String? subtitle;
  final String? description;
  final bool useErrorDialogs;

  const BiometricOptions({
    this.stickyAuth = false,
    this.sensitiveTransaction = false,
    this.reason,
    this.title,
    this.subtitle,
    this.description,
    this.useErrorDialogs = true,
  });
}

class KeyGenerationOptions {
  final bool userAuthenticationRequired;
  final int userAuthenticationValiditySeconds;
  final bool useEcdsa;
  final int keySize;
  final bool useSecureHardware;

  const KeyGenerationOptions({
    this.userAuthenticationRequired = true,
    this.userAuthenticationValiditySeconds = 30,
    this.useEcdsa = true,
    this.keySize = 2048,
    this.useSecureHardware = true,
  });
}

class KeyGenerationResult {
  final bool success;
  final String? publicKeyPem;
  final BiometricError? error;
  final String? errorMessage;

  const KeyGenerationResult({
    required this.success,
    this.publicKeyPem,
    this.error,
    this.errorMessage,
  });

  factory KeyGenerationResult.success(String publicKeyPem) =>
      KeyGenerationResult(success: true, publicKeyPem: publicKeyPem);

  factory KeyGenerationResult.failure(BiometricError error, [String? message]) =>
      KeyGenerationResult(success: false, error: error, errorMessage: message);
}

class SignatureResult {
  final bool success;
  final Uint8List? signature;
  final BiometricError? error;
  final String? errorMessage;

  const SignatureResult({
    required this.success,
    this.signature,
    this.error,
    this.errorMessage,
  });

  factory SignatureResult.success(Uint8List signature) =>
      SignatureResult(success: true, signature: signature);

  factory SignatureResult.failure(BiometricError error, [String? message]) =>
      SignatureResult(success: false, error: error, errorMessage: message);
}

void main() {
  runApp(const MyApp());
}

void main() {
  runApp(const MyApp());
}

class MyApp extends StatefulWidget {
  const MyApp({super.key});

  @override
  State<MyApp> createState() => _MyAppState();
}

class _MyAppState extends State<MyApp> {
  final fp.FingerprintPro _fingerprintPro = fp.FingerprintPro();

  bool _canAuthenticate = false;
  List<BiometricType> _availableBiometrics = [];
  String _status = 'Initializing...';
  String _generatedKeyAlias = '';
  String _publicKeyPem = '';
  String _signatureResult = '';

  @override
  void initState() {
    super.initState();
    _initializeBiometrics();
  }

  Future<void> _initializeBiometrics() async {
    try {
      // Check if biometric authentication is available
      _canAuthenticate = await _fingerprintPro.canAuthenticate();
      if (_canAuthenticate) {
        _availableBiometrics = await _fingerprintPro.getAvailableBiometrics();
      }

      setState(() {
        _status = _canAuthenticate
            ? 'Biometric authentication available'
            : 'Biometric authentication not available';
      });
    } catch (e) {
      setState(() {
        _status = 'Error initializing biometrics: $e';
      });
    }
  }

  Future<void> _authenticateUser() async {
    try {
      setState(() {
        _status = 'Authenticating...';
      });

      final result = await _fingerprintPro.authenticate(
        reason: 'Please authenticate to access the app',
        options: const BiometricOptions(
          stickyAuth: false,
          useErrorDialogs: true,
        ),
      );

      setState(() {
        if (result.success) {
          _status = 'Authentication successful!';
        } else {
          _status = 'Authentication failed: ${result.error != null ? result.error!.description : 'Unknown error'}';
        }
      });
    } catch (e) {
      setState(() {
        _status = 'Authentication error: $e';
      });
    }
  }

  Future<void> _generateKeyPair() async {
    try {
      setState(() {
        _status = 'Generating key pair...';
      });

      final result = await _fingerprintPro.generateKeyPair(
        keyAlias: 'example_key_${DateTime.now().millisecondsSinceEpoch}',
        options: const KeyGenerationOptions(
          userAuthenticationRequired: true,
          useEcdsa: true,
        ),
      );

      if (result.success && result.publicKeyPem != null) {
        setState(() {
          _generatedKeyAlias = 'example_key_${DateTime.now().millisecondsSinceEpoch}';
          _publicKeyPem = result.publicKeyPem!;
          _status = 'Key pair generated successfully!';
        });
      } else {
        setState(() {
          _status = 'Key generation failed: ${result.error != null ? result.error!.description : 'Unknown error'}';
        });
      }
    } catch (e) {
      setState(() {
        _status = 'Key generation error: $e';
      });
    }
  }

  Future<void> _signData() async {
    if (_generatedKeyAlias.isEmpty) {
      setState(() {
        _status = 'Please generate a key pair first';
      });
      return;
    }

    try {
      setState(() {
        _status = 'Signing data...';
      });

      // Sample data to sign
      const data = 'Hello, World! This is sample data to sign.';
      final dataBytes = utf8.encode(data);

      final result = await _fingerprintPro.signWithKey(
        keyAlias: _generatedKeyAlias,
        data: Uint8List.fromList(dataBytes),
      );

      if (result.success && result.signature != null) {
        setState(() {
          _signatureResult = 'Signature created: ${result.signature!.length} bytes';
          _status = 'Data signed successfully!';
        });
      } else {
        setState(() {
          _status = 'Signing failed: ${result.error != null ? result.error!.description : 'Unknown error'}';
        });
      }
    } catch (e) {
      setState(() {
        _status = 'Signing error: $e';
      });
    }
  }

  Future<void> _removeKey() async {
    if (_generatedKeyAlias.isEmpty) {
      setState(() {
        _status = 'No key to remove';
      });
      return;
    }

    try {
      setState(() {
        _status = 'Removing key...';
      });

      final success = await _fingerprintPro.removeKey(_generatedKeyAlias);

      if (success) {
        setState(() {
          _generatedKeyAlias = '';
          _publicKeyPem = '';
          _signatureResult = '';
          _status = 'Key removed successfully!';
        });
      } else {
        setState(() {
          _status = 'Failed to remove key';
        });
      }
    } catch (e) {
      setState(() {
        _status = 'Remove key error: $e';
      });
    }
  }

  Future<void> _listKeys() async {
    try {
      setState(() {
        _status = 'Listing keys...';
      });

      final keys = await _fingerprintPro.listKeys();

      setState(() {
        _status = 'Available keys: ${keys.join(', ')}';
      });
    } catch (e) {
      setState(() {
        _status = 'List keys error: $e';
      });
    }
  }

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: Scaffold(
        appBar: AppBar(
          title: const Text('Fingerprint Pro Example'),
        ),
        body: SingleChildScrollView(
          padding: const EdgeInsets.all(16.0),
          child: Column(
            crossAxisAlignment: CrossAxisAlignment.stretch,
            children: [
              // Status Card
              Card(
                child: Padding(
                  padding: const EdgeInsets.all(16.0),
                  child: Column(
                    crossAxisAlignment: CrossAxisAlignment.start,
                    children: [
                      Text(
                        'Status: $_status',
                        style: const TextStyle(fontSize: 16),
                      ),
                      const SizedBox(height: 8),
                      Text(
                        'Available Biometrics: ${_availableBiometrics.map((e) => e.name).join(', ')}',
                        style: const TextStyle(fontSize: 14, color: Colors.grey),
                      ),
                    ],
                  ),
                ),
              ),

              const SizedBox(height: 16),

              // Biometric Authentication Section
              Card(
                child: Padding(
                  padding: const EdgeInsets.all(16.0),
                  child: Column(
                    crossAxisAlignment: CrossAxisAlignment.start,
                    children: [
                      const Text(
                        'Biometric Authentication',
                        style: TextStyle(fontSize: 18, fontWeight: FontWeight.bold),
                      ),
                      const SizedBox(height: 8),
                      const Text(
                        'Simple biometric authentication using local_auth wrapper.',
                      ),
                      const SizedBox(height: 16),
                      ElevatedButton(
                        onPressed: _canAuthenticate ? _authenticateUser : null,
                        child: const Text('Authenticate'),
                      ),
                    ],
                  ),
                ),
              ),

              const SizedBox(height: 16),

              // Key Management Section
              Card(
                child: Padding(
                  padding: const EdgeInsets.all(16.0),
                  child: Column(
                    crossAxisAlignment: CrossAxisAlignment.start,
                    children: [
                      const Text(
                        'Key Management',
                        style: TextStyle(fontSize: 18, fontWeight: FontWeight.bold),
                      ),
                      const SizedBox(height: 8),
                      const Text(
                        'Advanced key generation and signing with biometric authentication.',
                      ),
                      const SizedBox(height: 16),
                      Row(
                        children: [
                          Expanded(
                            child: ElevatedButton(
                              onPressed: _generateKeyPair,
                              child: const Text('Generate Key Pair'),
                            ),
                          ),
                          const SizedBox(width: 8),
                          Expanded(
                            child: ElevatedButton(
                              onPressed: _generatedKeyAlias.isNotEmpty ? _removeKey : null,
                              style: ElevatedButton.styleFrom(
                                backgroundColor: Colors.red,
                                foregroundColor: Colors.white,
                              ),
                              child: const Text('Remove Key'),
                            ),
                          ),
                        ],
                      ),
                      const SizedBox(height: 8),
                      ElevatedButton(
                        onPressed: _generatedKeyAlias.isNotEmpty ? _signData : null,
                        child: const Text('Sign Data'),
                      ),
                      const SizedBox(height: 8),
                      ElevatedButton(
                        onPressed: _listKeys,
                        child: const Text('List Keys'),
                      ),
                    ],
                  ),
                ),
              ),

              const SizedBox(height: 16),

              // Key Information Section
              if (_publicKeyPem.isNotEmpty)
                Card(
                  child: Padding(
                    padding: const EdgeInsets.all(16.0),
                    child: Column(
                      crossAxisAlignment: CrossAxisAlignment.start,
                      children: [
                        const Text(
                          'Generated Key Information',
                          style: TextStyle(fontSize: 18, fontWeight: FontWeight.bold),
                        ),
                        const SizedBox(height: 8),
                        Text(
                          'Key Alias: $_generatedKeyAlias',
                          style: const TextStyle(fontSize: 14),
                        ),
                        const SizedBox(height: 8),
                        const Text(
                          'Public Key (PEM):',
                          style: TextStyle(fontSize: 14, fontWeight: FontWeight.bold),
                        ),
                        const SizedBox(height: 4),
                        Container(
                          padding: const EdgeInsets.all(8),
                          decoration: BoxDecoration(
                            color: Colors.grey[100],
                            borderRadius: BorderRadius.circular(4),
                          ),
                          child: Text(
                            _publicKeyPem,
                            style: const TextStyle(
                              fontSize: 12,
                              fontFamily: 'monospace',
                            ),
                          ),
                        ),
                      ],
                    ),
                  ),
                ),

              // Signature Result Section
              if (_signatureResult.isNotEmpty)
                Card(
                  child: Padding(
                    padding: const EdgeInsets.all(16.0),
                    child: Column(
                      crossAxisAlignment: CrossAxisAlignment.start,
                      children: [
                        const Text(
                          'Signature Result',
                          style: TextStyle(fontSize: 18, fontWeight: FontWeight.bold),
                        ),
                        const SizedBox(height: 8),
                        Text(_signatureResult),
                      ],
                    ),
                  ),
                ),

              const SizedBox(height: 16),

              // Information Card
              Card(
                child: Padding(
                  padding: const EdgeInsets.all(16.0),
                  child: Column(
                    crossAxisAlignment: CrossAxisAlignment.start,
                    children: [
                      const Text(
                        'About This Example',
                        style: TextStyle(fontSize: 18, fontWeight: FontWeight.bold),
                      ),
                      const SizedBox(height: 8),
                      const Text(
                        'This example demonstrates both modes of fingerprint_pro:\n\n'
                        '1. Simple biometric authentication (Authenticate button)\n'
                        '2. Advanced key management with biometric-protected signing (Generate Key Pair, Sign Data)\n\n'
                        'The advanced mode generates ECDSA key pairs in the device\'s secure keystore/keychain, '
                        'protected by biometric authentication. The public key can be shared with your server '
                        'for signature verification.',
                      ),
                    ],
                  ),
                ),
              ),
            ],
          ),
        ),
      ),
    );
  }
}
0
likes
140
points
15
downloads

Publisher

unverified uploader

Weekly Downloads

Secure biometric authentication and keystore-based signature system for Flutter, providing both simple and advanced fingerprint/face unlock features.

Homepage

Documentation

API reference

License

MIT (license)

Dependencies

crypto, flutter, local_auth, plugin_platform_interface

More

Packages that depend on fingerprint_pro

Packages that implement fingerprint_pro