app_fortress 1.0.1 copy "app_fortress: ^1.0.1" to clipboard
app_fortress: ^1.0.1 copied to clipboard

Production-grade multi-layer app security - SSL Pinning, Anti-Debug, Code Obfuscation, Play Integrity (Android), App Attest (iOS), Root/Jailbreak detection, and Native C protection layer.

example/lib/main.dart

import 'package:flutter/material.dart';
import 'package:flutter/foundation.dart';
import 'package:app_fortress/app_fortress.dart';

// =============================================================================
// CONFIGURATION - Update these values for your production app
// =============================================================================

class AppSecurityConfig {
  // Google Cloud Project Number (for Play Integrity API)
  // Get from: Google Cloud Console > Project Settings
  static const int cloudProjectNumber = 123456789;

  // Your app's release signing certificate SHA-256 fingerprint
  // Get with: keytool -list -v -keystore your-release.keystore
  // Or from Google Play Console > App Integrity
  static const List<String> expectedSignatures = [
    // Add your release signature here (remove colons)
    // Example: 'A1B2C3D4E5F6...'
  ];
}

// =============================================================================
// MAIN ENTRY POINT
// =============================================================================

void main() async {
  WidgetsFlutterBinding.ensureInitialized();

  // Configure App Fortress
  // Development: permissive settings for testing
  // Production: strict security (blocks rooted, emulator, debugger, hooking, proxy)
  await AppFortress.configure(
    cloudProjectNumber: AppSecurityConfig.cloudProjectNumber,
    config: kDebugMode
        ? SecurityConfig.development() // Permissive for testing
        : SecurityConfig.production(
            expectedSignatures: AppSecurityConfig.expectedSignatures,
            blockOnProxy: true, // Block proxy/MITM tools
            blockOnVpn: false, // Allow VPN (optional)
          ),
  );

  runApp(const MyApp());
}

// =============================================================================
// APP WITH SECURITY GATE
// =============================================================================

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

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'App Fortress Demo',
      debugShowCheckedModeBanner: false,
      theme: ThemeData(
        colorScheme: ColorScheme.fromSeed(seedColor: Colors.indigo),
        useMaterial3: true,
      ),
      home: SecurityGate(
        onSecurityCheckFailed: (status) {
          debugPrint('Security threats detected: ${status.threats}');
        },
        onSecurityCheckPassed: (status) {
          debugPrint('Security check passed');
        },
        loadingWidget: const _LoadingScreen(),
        child: const HomePage(),
      ),
    );
  }
}

class _LoadingScreen extends StatelessWidget {
  const _LoadingScreen();

  @override
  Widget build(BuildContext context) {
    return const Scaffold(
      body: Center(
        child: Column(
          mainAxisAlignment: MainAxisAlignment.center,
          children: [
            CircularProgressIndicator(),
            SizedBox(height: 16),
            Text('Verifying security...'),
          ],
        ),
      ),
    );
  }
}

// =============================================================================
// HOME PAGE - SECURITY DASHBOARD
// =============================================================================

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

  @override
  State<HomePage> createState() => _HomePageState();
}

class _HomePageState extends State<HomePage> {
  SecurityStatus? _status;
  DeviceSecurityInfo? _deviceInfo;
  bool _isLoading = false;

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

  Future<void> _runSecurityCheck() async {
    setState(() => _isLoading = true);
    try {
      final status = await AppFortress.runSecurityCheck();
      final info = await AppFortress.getDeviceSecurityInfo();
      setState(() {
        _status = status;
        _deviceInfo = info;
      });
    } finally {
      setState(() => _isLoading = false);
    }
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: const Text('App Fortress'),
        backgroundColor: Theme.of(context).colorScheme.inversePrimary,
        actions: [
          IconButton(
            icon: const Icon(Icons.refresh),
            onPressed: _runSecurityCheck,
          ),
        ],
      ),
      body: _isLoading
          ? const Center(child: CircularProgressIndicator())
          : RefreshIndicator(
              onRefresh: _runSecurityCheck,
              child: ListView(
                padding: const EdgeInsets.all(16),
                children: [
                  _buildStatusCard(),
                  const SizedBox(height: 16),
                  _buildSecurityChecksCard(),
                  const SizedBox(height: 16),
                  _buildDeviceInfoCard(),
                  const SizedBox(height: 16),
                  _buildActionsCard(),
                ],
              ),
            ),
    );
  }

  Widget _buildStatusCard() {
    final isSecure = _status?.isSecure ?? false;
    return Card(
      color: isSecure ? Colors.green[50] : Colors.red[50],
      child: Padding(
        padding: const EdgeInsets.all(20),
        child: Row(
          children: [
            Icon(
              isSecure ? Icons.verified_user : Icons.gpp_bad,
              size: 48,
              color: isSecure ? Colors.green : Colors.red,
            ),
            const SizedBox(width: 16),
            Expanded(
              child: Column(
                crossAxisAlignment: CrossAxisAlignment.start,
                children: [
                  Text(
                    isSecure ? 'SECURE' : 'THREATS DETECTED',
                    style: TextStyle(
                      fontSize: 20,
                      fontWeight: FontWeight.bold,
                      color: isSecure ? Colors.green[800] : Colors.red[800],
                    ),
                  ),
                  Text(
                    isSecure
                        ? 'No security issues found'
                        : '${_status?.threats.length ?? 0} issue(s) detected',
                    style: TextStyle(
                      color: isSecure ? Colors.green[600] : Colors.red[600],
                    ),
                  ),
                ],
              ),
            ),
          ],
        ),
      ),
    );
  }

  Widget _buildSecurityChecksCard() {
    return Card(
      child: Padding(
        padding: const EdgeInsets.all(16),
        child: Column(
          crossAxisAlignment: CrossAxisAlignment.start,
          children: [
            const Row(
              children: [
                Icon(Icons.security, color: Colors.indigo),
                SizedBox(width: 8),
                Text(
                  'Security Checks',
                  style: TextStyle(fontSize: 18, fontWeight: FontWeight.bold),
                ),
              ],
            ),
            const Divider(),
            _buildCheckItem('Root/Jailbreak', _deviceInfo?.isRooted ?? false),
            _buildCheckItem('Emulator', _deviceInfo?.isEmulator ?? false),
            _buildCheckItem(
                'Debugger', _deviceInfo?.isDebuggerAttached ?? false),
            _buildCheckItem('Hooking', _deviceInfo?.isHookingDetected ?? false),
            _buildCheckItem('Debug Build', _deviceInfo?.isDebuggable ?? false),
            _buildCheckItem(
                'Proxy Enabled', _deviceInfo?.isProxyEnabled ?? false),
            _buildCheckItem('VPN Active', _deviceInfo?.isVpnActive ?? false),
          ],
        ),
      ),
    );
  }

  Widget _buildCheckItem(String label, bool detected) {
    return Padding(
      padding: const EdgeInsets.symmetric(vertical: 8),
      child: Row(
        children: [
          Icon(
            detected ? Icons.warning_amber : Icons.check_circle,
            color: detected ? Colors.orange : Colors.green,
            size: 20,
          ),
          const SizedBox(width: 12),
          Expanded(child: Text(label)),
          Container(
            padding: const EdgeInsets.symmetric(horizontal: 8, vertical: 4),
            decoration: BoxDecoration(
              color: detected ? Colors.orange[100] : Colors.green[100],
              borderRadius: BorderRadius.circular(12),
            ),
            child: Text(
              detected ? 'DETECTED' : 'OK',
              style: TextStyle(
                fontSize: 12,
                fontWeight: FontWeight.bold,
                color: detected ? Colors.orange[800] : Colors.green[800],
              ),
            ),
          ),
        ],
      ),
    );
  }

  Widget _buildDeviceInfoCard() {
    return Card(
      child: Padding(
        padding: const EdgeInsets.all(16),
        child: Column(
          crossAxisAlignment: CrossAxisAlignment.start,
          children: [
            const Row(
              children: [
                Icon(Icons.phone_android, color: Colors.indigo),
                SizedBox(width: 8),
                Text(
                  'Device Info',
                  style: TextStyle(fontSize: 18, fontWeight: FontWeight.bold),
                ),
              ],
            ),
            const Divider(),
            _buildInfoRow('Platform', _deviceInfo?.platform ?? '-'),
            _buildInfoRow('Model', _deviceInfo?.model ?? '-'),
            _buildInfoRow('OS Version', _deviceInfo?.osVersion ?? '-'),
            _buildInfoRow('App Version', _deviceInfo?.appVersion ?? '-'),
            _buildInfoRow('Install Source', _deviceInfo?.installSource ?? '-'),
          ],
        ),
      ),
    );
  }

  Widget _buildInfoRow(String label, String value) {
    return Padding(
      padding: const EdgeInsets.symmetric(vertical: 4),
      child: Row(
        mainAxisAlignment: MainAxisAlignment.spaceBetween,
        children: [
          Text(label, style: const TextStyle(color: Colors.grey)),
          Flexible(
            child: Text(
              value,
              textAlign: TextAlign.end,
              overflow: TextOverflow.ellipsis,
            ),
          ),
        ],
      ),
    );
  }

  Widget _buildActionsCard() {
    return Card(
      child: Padding(
        padding: const EdgeInsets.all(16),
        child: Column(
          crossAxisAlignment: CrossAxisAlignment.start,
          children: [
            const Row(
              children: [
                Icon(Icons.touch_app, color: Colors.indigo),
                SizedBox(width: 8),
                Text(
                  'Actions',
                  style: TextStyle(fontSize: 18, fontWeight: FontWeight.bold),
                ),
              ],
            ),
            const Divider(),
            const SizedBox(height: 8),
            _buildActionButton(
              'Request Attestation',
              Icons.verified,
              Colors.green,
              _requestAttestation,
            ),
            const SizedBox(height: 8),
            _buildActionButton(
              'Verify Signature',
              Icons.fingerprint,
              Colors.orange,
              _verifySignature,
            ),
            const SizedBox(height: 8),
            _buildActionButton(
              'Quick Security Check',
              Icons.flash_on,
              Colors.blue,
              _quickCheck,
            ),
          ],
        ),
      ),
    );
  }

  Widget _buildActionButton(
    String label,
    IconData icon,
    Color color,
    VoidCallback onPressed,
  ) {
    return SizedBox(
      width: double.infinity,
      child: ElevatedButton.icon(
        onPressed: onPressed,
        icon: Icon(icon),
        label: Text(label),
        style: ElevatedButton.styleFrom(
          backgroundColor: color,
          foregroundColor: Colors.white,
          padding: const EdgeInsets.symmetric(vertical: 12),
        ),
      ),
    );
  }

  Future<void> _requestAttestation() async {
    setState(() => _isLoading = true);
    try {
      final nonce =
          'nonce-${DateTime.now().millisecondsSinceEpoch}-wafeesrgrrewraewagfafwaf';
      final result = await AppFortress.requestAttestation(nonce: nonce);
      if (!mounted) return;
      _showResultDialog(
        'Attestation Success',
        'Token received (${result.token.length} chars)\n\nSend this to your server for verification.',
        true,
      );
    } on AttestationException catch (e) {
      if (!mounted) return;
      _showResultDialog('Attestation Failed', e.message, false);
    } finally {
      setState(() => _isLoading = false);
    }
  }

  Future<void> _verifySignature() async {
    setState(() => _isLoading = true);
    try {
      final isValid = await AppFortress.verifySignature(
        expectedSignatures: AppSecurityConfig.expectedSignatures,
      );
      if (!mounted) return;
      _showResultDialog(
        isValid ? 'Signature Valid' : 'Signature Invalid',
        isValid
            ? 'App signature matches expected value.'
            : 'WARNING: App may have been tampered with!',
        isValid,
      );
    } finally {
      setState(() => _isLoading = false);
    }
  }

  Future<void> _quickCheck() async {
    setState(() => _isLoading = true);
    try {
      final status = await AppFortress.quickSecurityCheck();
      if (!mounted) return;
      _showResultDialog(
        status.isSecure ? 'Secure' : 'Issues Found',
        status.isSecure
            ? 'Quick check passed!'
            : 'Threats: ${status.threats.map((t) => t.code).join(', ')}',
        status.isSecure,
      );
    } finally {
      setState(() => _isLoading = false);
    }
  }

  void _showResultDialog(String title, String message, bool success) {
    showDialog(
      context: context,
      builder: (ctx) => AlertDialog(
        title: Row(
          children: [
            Icon(
              success ? Icons.check_circle : Icons.error,
              color: success ? Colors.green : Colors.red,
            ),
            const SizedBox(width: 8),
            Expanded(child: Text(title)),
          ],
        ),
        content: Text(message),
        actions: [
          TextButton(
            onPressed: () => Navigator.pop(ctx),
            child: const Text('OK'),
          ),
        ],
      ),
    );
  }
}
4
likes
150
points
156
downloads

Publisher

unverified uploader

Weekly Downloads

Production-grade multi-layer app security - SSL Pinning, Anti-Debug, Code Obfuscation, Play Integrity (Android), App Attest (iOS), Root/Jailbreak detection, and Native C protection layer.

Repository (GitHub)
View/report issues

Topics

#security #ssl-pinning #root-detection #play-integrity #anti-tampering

Documentation

API reference

License

MIT (license)

Dependencies

flutter, http, plugin_platform_interface

More

Packages that depend on app_fortress

Packages that implement app_fortress