zk_vault 0.1.3 copy "zk_vault: ^0.1.3" to clipboard
zk_vault: ^0.1.3 copied to clipboard

Zero-Knowledge style secure storage for Flutter/Dart applications with platform KMS integration

example/lib/main.dart

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

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

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

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'ZK Vault Example',
      theme: ThemeData(
        primarySwatch: Colors.blue,
      ),
      home: const VaultDemoScreen(),
    );
  }
}

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

  @override
  State<VaultDemoScreen> createState() => _VaultDemoScreenState();
}

class _VaultDemoScreenState extends State<VaultDemoScreen> {
  ZKVault? _vault;
  // PlatformKMS instance is constructed when needed; no persistent field required.
  final List<String> _logs = <String>[];
  bool _isLoading = false;
  bool _useNativeKms = true;

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: const Text('ZK Vault Demo'),
      ),
      body: Column(
        children: <Widget>[
          Padding(
            padding: const EdgeInsets.all(16.0),
            child: Column(
              crossAxisAlignment: CrossAxisAlignment.stretch,
              children: <Widget>[
                Card(
                  child: Padding(
                    padding: const EdgeInsets.all(16.0),
                    child: Column(
                      crossAxisAlignment: CrossAxisAlignment.start,
                      children: <Widget>[
                        const Text('KMS Selection', style: TextStyle(fontWeight: FontWeight.bold)),
                        SwitchListTile(
                          title: Text(_useNativeKms ? 'Native KMS (Hardware)' : 'Mock KMS (Testing)'),
                          subtitle: Text(_useNativeKms 
                            ? 'Uses Android Keystore / iOS Secure Enclave' 
                            : 'Software-only implementation for testing'),
                          value: _useNativeKms,
                          onChanged: _vault == null ? (bool value) {
                            setState(() => _useNativeKms = value);
                          } : null,
                        ),
                      ],
                    ),
                  ),
                ),
                const SizedBox(height: 8),
                ElevatedButton(
                  onPressed: _isLoading ? null : _checkCapabilities,
                  child: const Text('Check Hardware Capabilities'),
                ),
                const SizedBox(height: 8),
                ElevatedButton(
                  onPressed: _isLoading ? null : _openVault,
                  child: Text(_vault == null ? 'Open Vault' : 'Vault Opened'),
                ),
                const SizedBox(height: 8),
                ElevatedButton(
                  onPressed: _vault == null || _isLoading ? null : _storeData,
                  child: const Text('Store Sample Data'),
                ),
                const SizedBox(height: 8),
                ElevatedButton(
                  onPressed: _vault == null || _isLoading ? null : _retrieveData,
                  child: const Text('Retrieve Data'),
                ),
                const SizedBox(height: 8),
                ElevatedButton(
                  onPressed: _vault == null || _isLoading ? null : _listKeys,
                  child: const Text('List Keys'),
                ),
                const SizedBox(height: 8),
                ElevatedButton(
                  onPressed: _vault == null || _isLoading ? null : _lockVault,
                  child: const Text('Lock Vault'),
                ),
                const SizedBox(height: 8),
                ElevatedButton(
                  onPressed: _isLoading ? null : _clearLogs,
                  child: const Text('Clear Logs'),
                ),
              ],
            ),
          ),
          const Divider(),
          Expanded(
            child: Container(
              padding: const EdgeInsets.all(16.0),
              child: Column(
                  crossAxisAlignment: CrossAxisAlignment.start,
                  children: <Widget>[
                  const Text(
                    'Logs:',
                    style: TextStyle(fontWeight: FontWeight.bold),
                  ),
                  const SizedBox(height: 8),
                  Expanded(
                    child: Container(
                      width: double.infinity,
                      padding: const EdgeInsets.all(8),
                      decoration: BoxDecoration(
                        border: Border.all(color: Colors.grey),
                        borderRadius: BorderRadius.circular(4),
                      ),
                      child: SingleChildScrollView(
                                child: Text(
                          _logs.join('\n'),
                          style: const TextStyle(
                            fontFamily: 'monospace',
                            fontSize: 12,
                          ),
                        ),
                      ),
                    ),
                  ),
                ],
              ),
            ),
          ),
          if (_isLoading)
            const LinearProgressIndicator(),
        ],
      ),
    );
  }

  void _log(String message) {
    setState(() {
      _logs.add('[${DateTime.now().toIso8601String()}] $message');
    });
  }

  Future<void> _checkCapabilities() async {
    setState(() => _isLoading = true);
    try {
      _log('Checking hardware capabilities...');
      
      if (_useNativeKms) {
        try {
          final PlatformKMS kms = NativePlatformKMS();
          final bool hardwareBacked = await kms.isHardwareBacked();
          final bool biometricAvailable = await kms.isBiometricAvailable();
          
          _log('✓ Native KMS capabilities:');
          _log('  - Hardware-backed: $hardwareBacked');
          _log('  - Biometric available: $biometricAvailable');
          
          if (!hardwareBacked) {
            _log('⚠ Warning: Hardware KMS not available on this device');
          }
          if (!biometricAvailable) {
            _log('⚠ Warning: Biometric authentication not available');
          }
        } on SecureEnclaveUnavailableException catch (e) {
          _log('✗ Native KMS unavailable: $e');
          _log('  Consider using Mock KMS for testing');
        }
      } else {
  final PlatformKMS kms = MockPlatformKMS();
  final bool hardwareBacked = await kms.isHardwareBacked();
  final bool biometricAvailable = await kms.isBiometricAvailable();
        
        _log('✓ Mock KMS capabilities:');
        _log('  - Hardware-backed: $hardwareBacked (simulated)');
        _log('  - Biometric available: $biometricAvailable (simulated)');
        _log('  - Note: Mock KMS is for testing only');
      }
    } catch (e) {
      _log('✗ Failed to check capabilities: $e');
    } finally {
      setState(() => _isLoading = false);
    }
  }

  Future<void> _openVault() async {
    setState(() => _isLoading = true);
    try {
      _log('Opening vault...');
      _log('  - KMS: ${_useNativeKms ? "Native (Hardware)" : "Mock (Testing)"}');
      _log('  - Biometric required: true');
      
      PlatformKMS kms;
      if (_useNativeKms) {
        kms = NativePlatformKMS();
        _log('  - Using Android Keystore / iOS Secure Enclave');
      } else {
        kms = MockPlatformKMS();
        _log('  - Using software-only mock implementation');
      }
      
      // Open vault with biometric requirement
      _vault = await ZKVault.open(
        'demo_vault',
        requireBiometric: true,
        kms: kms,
      );
      
      _log('✓ Vault opened successfully');
      _log('  - Vault ID: demo_vault');
      
      // Show additional info about the KMS being used
      if (_useNativeKms) {
        final bool hardwareBacked = await kms.isHardwareBacked();
        _log('  - Hardware-backed: $hardwareBacked');
      }
    } catch (e) {
      _log('✗ Failed to open vault: $e');
      if (e is SecureEnclaveUnavailableException) {
        _log('  Try switching to Mock KMS or check device capabilities');
      }
    } finally {
      setState(() => _isLoading = false);
    }
  }

  Future<void> _storeData() async {
    setState(() => _isLoading = true);
    try {
      _log('Storing sample data...');
      
  // Store some sample data
  final Uint8List sampleData = Uint8List.fromList('Hello, ZK Vault!'.codeUnits);
  await _vault!.set('greeting', sampleData);
      
  final Uint8List secretData = Uint8List.fromList('This is a secret message'.codeUnits);
  await _vault!.set('secret', secretData);
      
  final Uint8List numbers = Uint8List.fromList(<int>[1, 2, 3, 4, 5, 42, 255]);
  await _vault!.set('numbers', numbers);
      
      _log('✓ Stored 3 items successfully');
      _log('  - greeting: "Hello, ZK Vault!"');
      _log('  - secret: "This is a secret message"');
      _log('  - numbers: [1, 2, 3, 4, 5, 42, 255]');
    } catch (e) {
      _log('✗ Failed to store data: $e');
    } finally {
      setState(() => _isLoading = false);
    }
  }

  Future<void> _retrieveData() async {
    setState(() => _isLoading = true);
    try {
      _log('Retrieving stored data...');
      
      // Retrieve the greeting
  final Uint8List? greeting = await _vault!.get('greeting');
      if (greeting != null) {
        final String greetingText = String.fromCharCodes(greeting);
        _log('✓ Retrieved greeting: "$greetingText"');
      } else {
        _log('✗ Greeting not found');
      }
      
      // Retrieve the secret
  final Uint8List? secret = await _vault!.get('secret');
      if (secret != null) {
        final String secretText = String.fromCharCodes(secret);
        _log('✓ Retrieved secret: "$secretText"');
      } else {
        _log('✗ Secret not found');
      }
      
      // Retrieve numbers
      final Uint8List? numbers = await _vault!.get('numbers');
      if (numbers != null) {
        _log('✓ Retrieved numbers: ${numbers.toList()}');
      } else {
        _log('✗ Numbers not found');
      }
      
      // Try to retrieve non-existent key
      final Uint8List? nonExistent = await _vault!.get('nonexistent');
      if (nonExistent == null) {
        _log('✓ Non-existent key correctly returned null');
      }
    } catch (e) {
      _log('✗ Failed to retrieve data: $e');
    } finally {
      setState(() => _isLoading = false);
    }
  }

  Future<void> _listKeys() async {
    setState(() => _isLoading = true);
    try {
      _log('Listing all keys...');
      
      final List<String> keys = await _vault!.keys();
      _log('✓ Found ${keys.length} keys: ${keys.join(', ')}');
      
      // Check if specific keys exist
      for (final String key in <String>['greeting', 'secret', 'numbers', 'nonexistent']) {
        final bool exists = await _vault!.contains(key);
        _log('  - $key: ${exists ? 'exists' : 'not found'}');
      }
    } catch (e) {
      _log('✗ Failed to list keys: $e');
    } finally {
      setState(() => _isLoading = false);
    }
  }

  Future<void> _lockVault() async {
    setState(() => _isLoading = true);
    try {
      _log('Locking vault...');
      
      await _vault!.lock();
      _vault = null;
      
      _log('✓ Vault locked successfully');
      _log('  - Master key cleared from memory');
      _log('  - Vault must be reopened to access data');
    } catch (e) {
      _log('✗ Failed to lock vault: $e');
    } finally {
      setState(() => _isLoading = false);
    }
  }

  void _clearLogs() {
    setState(() {
      _logs.clear();
    });
  }
}
1
likes
150
points
91
downloads

Publisher

unverified uploader

Weekly Downloads

Zero-Knowledge style secure storage for Flutter/Dart applications with platform KMS integration

Repository (GitHub)
View/report issues

Documentation

API reference

License

MIT (license)

Dependencies

cryptography, flutter, path, path_provider, synchronized

More

Packages that depend on zk_vault