import 'package:flutter_secure_storage/flutter_secure_storage.dart'; abstract interface class SecureStore { Future read(String key); Future write(String key, String value); Future delete(String key); } class DeviceStore implements SecureStore { final FlutterSecureStorage storage; const DeviceStore(this.storage); static const normal = DeviceStore( FlutterSecureStorage( aOptions: AndroidOptions( resetOnError: false, storageNamespace: 'sm_mobile', ), iOptions: IOSOptions( accountName: 'eu.chj.smMobile', accessibility: KeychainAccessibility.unlocked_this_device, synchronizable: false, ), ), ); /// The Vault data key, released only after a strong biometric check of /// the currently enrolled biometrics. There is deliberately no device /// passcode fallback: without biometrics the master password is needed. /// The system invalidates the key when biometrics are added or removed. static DeviceStore biometric(String title, {String negative = 'Cancel'}) => DeviceStore( FlutterSecureStorage( aOptions: AndroidOptions.biometric( resetOnError: false, enforceBiometrics: true, requireBiometricsPerOperation: true, biometricType: AndroidBiometricType.strongBiometricOnly, storageNamespace: 'sm_mobile_biometric_v2', biometricPromptTitle: title, biometricPromptNegativeButton: negative, ), iOptions: const IOSOptions( accountName: 'eu.chj.smMobile.biometric.v2', accessibility: KeychainAccessibility.passcode, synchronizable: false, accessControlFlags: [AccessControlFlag.biometryCurrentSet], ), ), ); /// Version 1 storage, which also accepted the device passcode. Only /// deleted, never read. static DeviceStore legacyBiometric() => const DeviceStore( FlutterSecureStorage( aOptions: AndroidOptions.biometric( resetOnError: false, enforceBiometrics: true, requireBiometricsPerOperation: true, storageNamespace: 'sm_mobile_biometric', ), iOptions: IOSOptions( accountName: 'eu.chj.smMobile.biometric', accessibility: KeychainAccessibility.passcode, synchronizable: false, accessControlFlags: [AccessControlFlag.userPresence], ), ), ); @override Future read(String key) => storage.read(key: key); @override Future write(String key, String value) => storage.write(key: key, value: value); @override Future delete(String key) => storage.delete(key: key); }