v2 #12
| @ -4,6 +4,8 @@ | |||||||
| // license that can be found in the LICENSE file or at | // license that can be found in the LICENSE file or at | ||||||
| // https://opensource.org/licenses/MIT. | // https://opensource.org/licenses/MIT. | ||||||
| 
 | 
 | ||||||
|  | import 'dart:io'; | ||||||
|  | 
 | ||||||
| import 'package:flutter/foundation.dart'; | import 'package:flutter/foundation.dart'; | ||||||
| import 'package:native_crypto/native_crypto.dart'; | import 'package:native_crypto/native_crypto.dart'; | ||||||
| import 'package:native_crypto_example/domain/data_sources/crypto_data_source.dart'; | import 'package:native_crypto_example/domain/data_sources/crypto_data_source.dart'; | ||||||
| @ -30,6 +32,29 @@ class NativeCryptoDataSourceImpl extends CryptoDataSource { | |||||||
|     return plainText; |     return plainText; | ||||||
|   } |   } | ||||||
| 
 | 
 | ||||||
|  |   @override | ||||||
|  |   Future<void> decryptFile( | ||||||
|  |     File cipherText, | ||||||
|  |     Uri folderResult, | ||||||
|  |     SecretKey key, | ||||||
|  |   ) async { | ||||||
|  |     final AES cipher = AES( | ||||||
|  |       key: key, | ||||||
|  |       mode: AESMode.gcm, | ||||||
|  |       padding: AESPadding.none, | ||||||
|  |     ); | ||||||
|  | 
 | ||||||
|  |     final plainText = File.fromUri( | ||||||
|  |       Uri.parse( | ||||||
|  |         '${folderResult.path}/${cipherText.path.split('/').last.replaceAll('.enc', '')}', | ||||||
|  |       ), | ||||||
|  |     ); | ||||||
|  |     await cipher.decryptFile( | ||||||
|  |       cipherText, | ||||||
|  |       plainText, | ||||||
|  |     ); | ||||||
|  |   } | ||||||
|  | 
 | ||||||
|   @override |   @override | ||||||
|   Future<SecretKey> deriveKeyFromPassword( |   Future<SecretKey> deriveKeyFromPassword( | ||||||
|     String password, { |     String password, { | ||||||
| @ -95,6 +120,27 @@ class NativeCryptoDataSourceImpl extends CryptoDataSource { | |||||||
|     return cipherText.bytes; |     return cipherText.bytes; | ||||||
|   } |   } | ||||||
| 
 | 
 | ||||||
|  |   @override | ||||||
|  |   Future<void> encryptFile( | ||||||
|  |     File plainText, | ||||||
|  |     Uri folderResult, | ||||||
|  |     SecretKey key, | ||||||
|  |   ) async { | ||||||
|  |     final AES cipher = AES( | ||||||
|  |       key: key, | ||||||
|  |       mode: AESMode.gcm, | ||||||
|  |       padding: AESPadding.none, | ||||||
|  |     ); | ||||||
|  | 
 | ||||||
|  |     final cipherText = File.fromUri( | ||||||
|  |       Uri.parse( | ||||||
|  |         '${folderResult.path}/${plainText.path.split('/').last}.enc', | ||||||
|  |       ), | ||||||
|  |     ); | ||||||
|  | 
 | ||||||
|  |     await cipher.encryptFile(plainText, cipherText); | ||||||
|  |   } | ||||||
|  | 
 | ||||||
|   @override |   @override | ||||||
|   Future<SecretKey> generateSecureRandom(int length) async { |   Future<SecretKey> generateSecureRandom(int length) async { | ||||||
|     final SecretKey sk = await SecretKey.fromSecureRandom(length); |     final SecretKey sk = await SecretKey.fromSecureRandom(length); | ||||||
|  | |||||||
| @ -6,6 +6,8 @@ | |||||||
| 
 | 
 | ||||||
| // ignore_for_file: implementation_imports | // ignore_for_file: implementation_imports | ||||||
| 
 | 
 | ||||||
|  | import 'dart:io'; | ||||||
|  | 
 | ||||||
| import 'package:flutter/foundation.dart'; | import 'package:flutter/foundation.dart'; | ||||||
| import 'package:native_crypto/native_crypto.dart'; | import 'package:native_crypto/native_crypto.dart'; | ||||||
| import 'package:native_crypto_example/domain/data_sources/crypto_data_source.dart'; | import 'package:native_crypto_example/domain/data_sources/crypto_data_source.dart'; | ||||||
| @ -37,6 +39,15 @@ class PointyCastleDataSourceImpl extends CryptoDataSource { | |||||||
|     return paddedPlainText; |     return paddedPlainText; | ||||||
|   } |   } | ||||||
| 
 | 
 | ||||||
|  |   @override | ||||||
|  |   Future<void> decryptFile( | ||||||
|  |     File cipherText, | ||||||
|  |     Uri folderResult, | ||||||
|  |     SecretKey key, | ||||||
|  |   ) async { | ||||||
|  |     throw UnimplementedError(); | ||||||
|  |   } | ||||||
|  | 
 | ||||||
|   @override |   @override | ||||||
|   Future<SecretKey> deriveKeyFromPassword( |   Future<SecretKey> deriveKeyFromPassword( | ||||||
|     String password, { |     String password, { | ||||||
| @ -125,7 +136,10 @@ class PointyCastleDataSourceImpl extends CryptoDataSource { | |||||||
| 
 | 
 | ||||||
|   @override |   @override | ||||||
|   Future<Uint8List> encryptWithIV( |   Future<Uint8List> encryptWithIV( | ||||||
|       Uint8List data, SecretKey key, Uint8List iv,) async { |     Uint8List data, | ||||||
|  |     SecretKey key, | ||||||
|  |     Uint8List iv, | ||||||
|  |   ) async { | ||||||
|     final gcm = GCMBlockCipher(AESEngine()) |     final gcm = GCMBlockCipher(AESEngine()) | ||||||
|       ..init( |       ..init( | ||||||
|         true, |         true, | ||||||
| @ -144,6 +158,15 @@ class PointyCastleDataSourceImpl extends CryptoDataSource { | |||||||
|     ); |     ); | ||||||
|   } |   } | ||||||
| 
 | 
 | ||||||
|  |   @override | ||||||
|  |   Future<void> encryptFile( | ||||||
|  |     File plainText, | ||||||
|  |     Uri folderResult, | ||||||
|  |     SecretKey key, | ||||||
|  |   ) async { | ||||||
|  |     throw UnimplementedError(); | ||||||
|  |   } | ||||||
|  | 
 | ||||||
|   @override |   @override | ||||||
|   Future<SecretKey> generateSecureRandom(int length) async { |   Future<SecretKey> generateSecureRandom(int length) async { | ||||||
|     if (_secureRandom == null) { |     if (_secureRandom == null) { | ||||||
|  | |||||||
| @ -4,6 +4,7 @@ | |||||||
| // license that can be found in the LICENSE file or at | // license that can be found in the LICENSE file or at | ||||||
| // https://opensource.org/licenses/MIT. | // https://opensource.org/licenses/MIT. | ||||||
| 
 | 
 | ||||||
|  | import 'dart:io'; | ||||||
| import 'dart:typed_data'; | import 'dart:typed_data'; | ||||||
| 
 | 
 | ||||||
| import 'package:native_crypto/native_crypto.dart'; | import 'package:native_crypto/native_crypto.dart'; | ||||||
| @ -30,6 +31,22 @@ class CryptoRepositoryImpl extends CryptoRepository { | |||||||
|         }, |         }, | ||||||
|       ); |       ); | ||||||
| 
 | 
 | ||||||
|  |   @override | ||||||
|  |   FutureOrResult<void> decryptFile( | ||||||
|  |     File cipherText, | ||||||
|  |     Uri folderResult, | ||||||
|  |     SecretKey key, | ||||||
|  |   ) => | ||||||
|  |       Result.tryCatchAsync( | ||||||
|  |         () async => cryptoDataSource.decryptFile(cipherText, folderResult, key), | ||||||
|  |         (error) { | ||||||
|  |           if (error is NativeCryptoException) { | ||||||
|  |             return ClientException('${error.message}'); | ||||||
|  |           } | ||||||
|  |           return ClientException(error.toString()); | ||||||
|  |         }, | ||||||
|  |       ); | ||||||
|  | 
 | ||||||
|   @override |   @override | ||||||
|   FutureOrResult<SecretKey> deriveKeyFromPassword( |   FutureOrResult<SecretKey> deriveKeyFromPassword( | ||||||
|     String password, { |     String password, { | ||||||
| @ -86,7 +103,10 @@ class CryptoRepositoryImpl extends CryptoRepository { | |||||||
| 
 | 
 | ||||||
|   @override |   @override | ||||||
|   FutureOrResult<Uint8List> encryptWithIV( |   FutureOrResult<Uint8List> encryptWithIV( | ||||||
|           Uint8List data, SecretKey key, Uint8List iv,) => |     Uint8List data, | ||||||
|  |     SecretKey key, | ||||||
|  |     Uint8List iv, | ||||||
|  |   ) => | ||||||
|       Result.tryCatchAsync( |       Result.tryCatchAsync( | ||||||
|         () async => cryptoDataSource.encryptWithIV(data, key, iv), |         () async => cryptoDataSource.encryptWithIV(data, key, iv), | ||||||
|         (error) { |         (error) { | ||||||
| @ -97,6 +117,22 @@ class CryptoRepositoryImpl extends CryptoRepository { | |||||||
|         }, |         }, | ||||||
|       ); |       ); | ||||||
| 
 | 
 | ||||||
|  |   @override | ||||||
|  |   FutureOrResult<void> encryptFile( | ||||||
|  |     File plainText, | ||||||
|  |     Uri folderResult, | ||||||
|  |     SecretKey key, | ||||||
|  |   ) => | ||||||
|  |       Result.tryCatchAsync( | ||||||
|  |         () async => cryptoDataSource.encryptFile(plainText, folderResult, key), | ||||||
|  |         (error) { | ||||||
|  |           if (error is NativeCryptoException) { | ||||||
|  |             return ClientException('${error.message}'); | ||||||
|  |           } | ||||||
|  |           return ClientException(error.toString()); | ||||||
|  |         }, | ||||||
|  |       ); | ||||||
|  | 
 | ||||||
|   @override |   @override | ||||||
|   FutureOrResult<SecretKey> generateSecureRandom(int length) => |   FutureOrResult<SecretKey> generateSecureRandom(int length) => | ||||||
|       Result.tryCatchAsync( |       Result.tryCatchAsync( | ||||||
|  | |||||||
| @ -0,0 +1,167 @@ | |||||||
|  | // Copyright 2019-2023 Hugo Pointcheval | ||||||
|  | // | ||||||
|  | // Use of this source code is governed by an MIT-style | ||||||
|  | // license that can be found in the LICENSE file or at | ||||||
|  | // https://opensource.org/licenses/MIT. | ||||||
|  | 
 | ||||||
|  | import 'dart:io'; | ||||||
|  | import 'dart:typed_data'; | ||||||
|  | 
 | ||||||
|  | import 'package:native_crypto/native_crypto.dart'; | ||||||
|  | import 'package:native_crypto_example/domain/data_sources/crypto_data_source.dart'; | ||||||
|  | import 'package:native_crypto_example/domain/entities/mode.dart'; | ||||||
|  | import 'package:native_crypto_example/domain/repositories/crypto_repository.dart'; | ||||||
|  | import 'package:wyatt_architecture/wyatt_architecture.dart'; | ||||||
|  | import 'package:wyatt_type_utils/wyatt_type_utils.dart'; | ||||||
|  | 
 | ||||||
|  | class CryptoRepositorySwitchableImpl extends CryptoRepository { | ||||||
|  |   CryptoRepositorySwitchableImpl({ | ||||||
|  |     required this.nativeCryptoDataSource, | ||||||
|  |     required this.pointyCastleDataSource, | ||||||
|  |     required this.currentMode, | ||||||
|  |   }); | ||||||
|  | 
 | ||||||
|  |   CryptoDataSource nativeCryptoDataSource; | ||||||
|  |   CryptoDataSource pointyCastleDataSource; | ||||||
|  |   Mode currentMode; | ||||||
|  | 
 | ||||||
|  |   set mode(Mode mode) { | ||||||
|  |     currentMode = mode; | ||||||
|  |   } | ||||||
|  | 
 | ||||||
|  |   CryptoDataSource get cryptoDataSource { | ||||||
|  |     if (currentMode is NativeCryptoMode) { | ||||||
|  |       return nativeCryptoDataSource; | ||||||
|  |     } else if (currentMode is PointyCastleMode) { | ||||||
|  |       return pointyCastleDataSource; | ||||||
|  |     } else { | ||||||
|  |       throw Exception('Unknown mode'); | ||||||
|  |     } | ||||||
|  |   } | ||||||
|  | 
 | ||||||
|  |   @override | ||||||
|  |   FutureOrResult<Uint8List> decrypt(Uint8List data, SecretKey key) => | ||||||
|  |       Result.tryCatchAsync( | ||||||
|  |         () async => cryptoDataSource.decrypt(data, key), | ||||||
|  |         (error) { | ||||||
|  |           if (error is NativeCryptoException) { | ||||||
|  |             return ClientException('${error.message}'); | ||||||
|  |           } | ||||||
|  |           return ClientException(error.toString()); | ||||||
|  |         }, | ||||||
|  |       ); | ||||||
|  | 
 | ||||||
|  |   @override | ||||||
|  |   FutureOrResult<void> decryptFile( | ||||||
|  |     File cipherText, | ||||||
|  |     Uri folderResult, | ||||||
|  |     SecretKey key, | ||||||
|  |   ) => | ||||||
|  |       Result.tryCatchAsync( | ||||||
|  |         () async => cryptoDataSource.decryptFile(cipherText, folderResult, key), | ||||||
|  |         (error) { | ||||||
|  |           if (error is NativeCryptoException) { | ||||||
|  |             return ClientException('${error.message}'); | ||||||
|  |           } | ||||||
|  |           return ClientException(error.toString()); | ||||||
|  |         }, | ||||||
|  |       ); | ||||||
|  | 
 | ||||||
|  |   @override | ||||||
|  |   FutureOrResult<SecretKey> deriveKeyFromPassword( | ||||||
|  |     String password, { | ||||||
|  |     required String salt, | ||||||
|  |   }) => | ||||||
|  |       Result.tryCatchAsync( | ||||||
|  |         () async => cryptoDataSource.deriveKeyFromPassword( | ||||||
|  |           password, | ||||||
|  |           salt: salt, | ||||||
|  |         ), | ||||||
|  |         (error) { | ||||||
|  |           if (error is NativeCryptoException) { | ||||||
|  |             return ClientException('${error.message}'); | ||||||
|  |           } | ||||||
|  |           return ClientException(error.toString()); | ||||||
|  |         }, | ||||||
|  |       ); | ||||||
|  | 
 | ||||||
|  |   @override | ||||||
|  |   FutureOrResult<Uint8List> hash(Hash hasher, Uint8List data) => | ||||||
|  |       Result.tryCatchAsync( | ||||||
|  |         () async => cryptoDataSource.hash(hasher, data), | ||||||
|  |         (error) { | ||||||
|  |           if (error is NativeCryptoException) { | ||||||
|  |             return ClientException('${error.message}'); | ||||||
|  |           } | ||||||
|  |           return ClientException(error.toString()); | ||||||
|  |         }, | ||||||
|  |       ); | ||||||
|  | 
 | ||||||
|  |   @override | ||||||
|  |   FutureOrResult<Uint8List> hmac(Hmac hmac, Uint8List data, SecretKey key) => | ||||||
|  |       Result.tryCatchAsync( | ||||||
|  |         () async => cryptoDataSource.hmac(hmac, data, key), | ||||||
|  |         (error) { | ||||||
|  |           if (error is NativeCryptoException) { | ||||||
|  |             return ClientException('${error.message}'); | ||||||
|  |           } | ||||||
|  |           return ClientException(error.toString()); | ||||||
|  |         }, | ||||||
|  |       ); | ||||||
|  | 
 | ||||||
|  |   @override | ||||||
|  |   FutureOrResult<Uint8List> encrypt(Uint8List data, SecretKey key) => | ||||||
|  |       Result.tryCatchAsync( | ||||||
|  |         () async => cryptoDataSource.encrypt(data, key), | ||||||
|  |         (error) { | ||||||
|  |           if (error is NativeCryptoException) { | ||||||
|  |             return ClientException('${error.message}'); | ||||||
|  |           } | ||||||
|  |           return ClientException(error.toString()); | ||||||
|  |         }, | ||||||
|  |       ); | ||||||
|  | 
 | ||||||
|  |   @override | ||||||
|  |   FutureOrResult<Uint8List> encryptWithIV( | ||||||
|  |     Uint8List data, | ||||||
|  |     SecretKey key, | ||||||
|  |     Uint8List iv, | ||||||
|  |   ) => | ||||||
|  |       Result.tryCatchAsync( | ||||||
|  |         () async => cryptoDataSource.encryptWithIV(data, key, iv), | ||||||
|  |         (error) { | ||||||
|  |           if (error is NativeCryptoException) { | ||||||
|  |             return ClientException('${error.message}'); | ||||||
|  |           } | ||||||
|  |           return ClientException(error.toString()); | ||||||
|  |         }, | ||||||
|  |       ); | ||||||
|  | 
 | ||||||
|  |   @override | ||||||
|  |   FutureOrResult<void> encryptFile( | ||||||
|  |     File plainText, | ||||||
|  |     Uri folderResult, | ||||||
|  |     SecretKey key, | ||||||
|  |   ) => | ||||||
|  |       Result.tryCatchAsync( | ||||||
|  |         () async => cryptoDataSource.encryptFile(plainText, folderResult, key), | ||||||
|  |         (error) { | ||||||
|  |           if (error is NativeCryptoException) { | ||||||
|  |             return ClientException('${error.message}'); | ||||||
|  |           } | ||||||
|  |           return ClientException(error.toString()); | ||||||
|  |         }, | ||||||
|  |       ); | ||||||
|  | 
 | ||||||
|  |   @override | ||||||
|  |   FutureOrResult<SecretKey> generateSecureRandom(int length) => | ||||||
|  |       Result.tryCatchAsync( | ||||||
|  |         () async => cryptoDataSource.generateSecureRandom(length), | ||||||
|  |         (error) { | ||||||
|  |           if (error is NativeCryptoException) { | ||||||
|  |             return ClientException('${error.message}'); | ||||||
|  |           } | ||||||
|  |           return ClientException(error.toString()); | ||||||
|  |         }, | ||||||
|  |       ); | ||||||
|  | } | ||||||
| @ -4,6 +4,8 @@ | |||||||
| // license that can be found in the LICENSE file or at | // license that can be found in the LICENSE file or at | ||||||
| // https://opensource.org/licenses/MIT. | // https://opensource.org/licenses/MIT. | ||||||
| 
 | 
 | ||||||
|  | import 'dart:io'; | ||||||
|  | 
 | ||||||
| import 'package:flutter/foundation.dart'; | import 'package:flutter/foundation.dart'; | ||||||
| import 'package:native_crypto/native_crypto.dart'; | import 'package:native_crypto/native_crypto.dart'; | ||||||
| import 'package:wyatt_architecture/wyatt_architecture.dart'; | import 'package:wyatt_architecture/wyatt_architecture.dart'; | ||||||
| @ -15,12 +17,22 @@ abstract class CryptoDataSource extends BaseDataSource { | |||||||
|     required String salt, |     required String salt, | ||||||
|   }); |   }); | ||||||
|   Future<Uint8List> encrypt(Uint8List data, SecretKey key); |   Future<Uint8List> encrypt(Uint8List data, SecretKey key); | ||||||
|  |   Future<void> encryptFile( | ||||||
|  |     File plainText, | ||||||
|  |     Uri folderResult, | ||||||
|  |     SecretKey key, | ||||||
|  |   ); | ||||||
|   Future<Uint8List> encryptWithIV( |   Future<Uint8List> encryptWithIV( | ||||||
|     Uint8List data, |     Uint8List data, | ||||||
|     SecretKey key, |     SecretKey key, | ||||||
|     Uint8List iv, |     Uint8List iv, | ||||||
|   ); |   ); | ||||||
|   Future<Uint8List> decrypt(Uint8List data, SecretKey key); |   Future<Uint8List> decrypt(Uint8List data, SecretKey key); | ||||||
|  |   Future<void> decryptFile( | ||||||
|  |     File cipherText, | ||||||
|  |     Uri folderResult, | ||||||
|  |     SecretKey key, | ||||||
|  |   ); | ||||||
|   Future<Uint8List> hash(Hash hasher, Uint8List data); |   Future<Uint8List> hash(Hash hasher, Uint8List data); | ||||||
|   Future<Uint8List> hmac(Hmac hmac, Uint8List data, SecretKey key); |   Future<Uint8List> hmac(Hmac hmac, Uint8List data, SecretKey key); | ||||||
| } | } | ||||||
|  | |||||||
| @ -4,6 +4,8 @@ | |||||||
| // license that can be found in the LICENSE file or at | // license that can be found in the LICENSE file or at | ||||||
| // https://opensource.org/licenses/MIT. | // https://opensource.org/licenses/MIT. | ||||||
| 
 | 
 | ||||||
|  | import 'dart:io'; | ||||||
|  | 
 | ||||||
| import 'package:flutter/foundation.dart'; | import 'package:flutter/foundation.dart'; | ||||||
| import 'package:native_crypto/native_crypto.dart'; | import 'package:native_crypto/native_crypto.dart'; | ||||||
| import 'package:wyatt_architecture/wyatt_architecture.dart'; | import 'package:wyatt_architecture/wyatt_architecture.dart'; | ||||||
| @ -15,12 +17,22 @@ abstract class CryptoRepository extends BaseRepository { | |||||||
|     required String salt, |     required String salt, | ||||||
|   }); |   }); | ||||||
|   FutureOrResult<Uint8List> encrypt(Uint8List data, SecretKey key); |   FutureOrResult<Uint8List> encrypt(Uint8List data, SecretKey key); | ||||||
|  |   FutureOrResult<void> encryptFile( | ||||||
|  |     File plainText, | ||||||
|  |     Uri folderResult, | ||||||
|  |     SecretKey key, | ||||||
|  |   ); | ||||||
|   FutureOrResult<Uint8List> encryptWithIV( |   FutureOrResult<Uint8List> encryptWithIV( | ||||||
|     Uint8List data, |     Uint8List data, | ||||||
|     SecretKey key, |     SecretKey key, | ||||||
|     Uint8List iv, |     Uint8List iv, | ||||||
|   ); |   ); | ||||||
|   FutureOrResult<Uint8List> decrypt(Uint8List data, SecretKey key); |   FutureOrResult<Uint8List> decrypt(Uint8List data, SecretKey key); | ||||||
|  |   FutureOrResult<void> decryptFile( | ||||||
|  |     File cipherText, | ||||||
|  |     Uri folderResult, | ||||||
|  |     SecretKey key, | ||||||
|  |   ); | ||||||
| 
 | 
 | ||||||
|   FutureOrResult<Uint8List> hash(Hash hasher, Uint8List data); |   FutureOrResult<Uint8List> hash(Hash hasher, Uint8List data); | ||||||
|   FutureOrResult<Uint8List> hmac(Hmac hmac, Uint8List data, SecretKey key); |   FutureOrResult<Uint8List> hmac(Hmac hmac, Uint8List data, SecretKey key); | ||||||
|  | |||||||
| @ -8,9 +8,11 @@ import 'package:flutter/material.dart'; | |||||||
| import 'package:flutter_bloc/flutter_bloc.dart'; | import 'package:flutter_bloc/flutter_bloc.dart'; | ||||||
| import 'package:native_crypto_example/core/get_it.dart'; | import 'package:native_crypto_example/core/get_it.dart'; | ||||||
| import 'package:native_crypto_example/data/data_sources/native_crypto_data_source_impl.dart'; | import 'package:native_crypto_example/data/data_sources/native_crypto_data_source_impl.dart'; | ||||||
| import 'package:native_crypto_example/data/repositories/crypto_repository_impl.dart'; | import 'package:native_crypto_example/data/data_sources/pointy_castle_data_source_impl.dart'; | ||||||
|  | import 'package:native_crypto_example/data/repositories/crypto_repository_switchable_impl.dart'; | ||||||
| import 'package:native_crypto_example/data/repositories/logger_repository_impl.dart'; | import 'package:native_crypto_example/data/repositories/logger_repository_impl.dart'; | ||||||
| import 'package:native_crypto_example/data/repositories/session_repository_impl.dart'; | import 'package:native_crypto_example/data/repositories/session_repository_impl.dart'; | ||||||
|  | import 'package:native_crypto_example/domain/entities/mode.dart'; | ||||||
| import 'package:native_crypto_example/domain/repositories/crypto_repository.dart'; | import 'package:native_crypto_example/domain/repositories/crypto_repository.dart'; | ||||||
| import 'package:native_crypto_example/domain/repositories/logger_repository.dart'; | import 'package:native_crypto_example/domain/repositories/logger_repository.dart'; | ||||||
| import 'package:native_crypto_example/domain/repositories/session_repository.dart'; | import 'package:native_crypto_example/domain/repositories/session_repository.dart'; | ||||||
| @ -28,6 +30,12 @@ class App extends StatelessWidget { | |||||||
|   final SessionRepository _sessionRepository = |   final SessionRepository _sessionRepository = | ||||||
|       SessionRepositoryImpl(sessionDataSource: getIt()); |       SessionRepositoryImpl(sessionDataSource: getIt()); | ||||||
| 
 | 
 | ||||||
|  |   final CryptoRepository _cryptoRepository = CryptoRepositorySwitchableImpl( | ||||||
|  |     nativeCryptoDataSource: getIt<NativeCryptoDataSourceImpl>(), | ||||||
|  |     pointyCastleDataSource: getIt<PointyCastleDataSourceImpl>(), | ||||||
|  |     currentMode: const NativeCryptoMode(), | ||||||
|  |   ); | ||||||
|  | 
 | ||||||
|   @override |   @override | ||||||
|   Widget build(BuildContext context) => MultiProvider( |   Widget build(BuildContext context) => MultiProvider( | ||||||
|         repositoryProviders: [ |         repositoryProviders: [ | ||||||
| @ -35,18 +43,17 @@ class App extends StatelessWidget { | |||||||
|           RepositoryProvider<SessionRepository>.value( |           RepositoryProvider<SessionRepository>.value( | ||||||
|             value: _sessionRepository, |             value: _sessionRepository, | ||||||
|           ), |           ), | ||||||
|           RepositoryProvider<CryptoRepository>( |           RepositoryProvider<CryptoRepository>.value(value: _cryptoRepository), | ||||||
|             create: (_) => CryptoRepositoryImpl( |  | ||||||
|               cryptoDataSource: getIt<NativeCryptoDataSourceImpl>(), |  | ||||||
|             ), |  | ||||||
|           ), |  | ||||||
|         ], |         ], | ||||||
|         blocProviders: [ |         blocProviders: [ | ||||||
|           BlocProvider<OutputCubit>( |           BlocProvider<OutputCubit>( | ||||||
|             create: (_) => OutputCubit(_loggerRepository), |             create: (_) => OutputCubit(_loggerRepository), | ||||||
|           ), |           ), | ||||||
|           BlocProvider<ModeSwitcherCubit>( |           BlocProvider<ModeSwitcherCubit>( | ||||||
|             create: (_) => ModeSwitcherCubit(_sessionRepository), |             create: (_) => ModeSwitcherCubit( | ||||||
|  |               _sessionRepository, | ||||||
|  |               _cryptoRepository, | ||||||
|  |             ), | ||||||
|           ) |           ) | ||||||
|         ], |         ], | ||||||
|         child: MaterialApp( |         child: MaterialApp( | ||||||
|  | |||||||
| @ -0,0 +1,132 @@ | |||||||
|  | // Copyright 2019-2023 Hugo Pointcheval | ||||||
|  | // | ||||||
|  | // Use of this source code is governed by an MIT-style | ||||||
|  | // license that can be found in the LICENSE file or at | ||||||
|  | // https://opensource.org/licenses/MIT. | ||||||
|  | 
 | ||||||
|  | import 'dart:async'; | ||||||
|  | 
 | ||||||
|  | import 'package:flutter/foundation.dart'; | ||||||
|  | import 'package:flutter_bloc/flutter_bloc.dart'; | ||||||
|  | import 'package:native_crypto_example/domain/entities/log_message.dart'; | ||||||
|  | import 'package:native_crypto_example/domain/entities/states.dart'; | ||||||
|  | import 'package:native_crypto_example/domain/repositories/crypto_repository.dart'; | ||||||
|  | import 'package:native_crypto_example/domain/repositories/logger_repository.dart'; | ||||||
|  | import 'package:native_crypto_example/domain/repositories/session_repository.dart'; | ||||||
|  | 
 | ||||||
|  | part 'benchmark_state.dart'; | ||||||
|  | 
 | ||||||
|  | class BenchmarkCubit extends Cubit<BenchmarkState> { | ||||||
|  |   BenchmarkCubit({ | ||||||
|  |     required this.sessionRepository, | ||||||
|  |     required this.loggerRepository, | ||||||
|  |     required this.cryptoRepository, | ||||||
|  |   }) : super(const BenchmarkState.initial()); | ||||||
|  |   final SessionRepository sessionRepository; | ||||||
|  |   final LoggerRepository loggerRepository; | ||||||
|  |   final CryptoRepository cryptoRepository; | ||||||
|  | 
 | ||||||
|  |   List<int> testedSizes = [ | ||||||
|  |     2097152, | ||||||
|  |     6291456, | ||||||
|  |     10485760, | ||||||
|  |     14680064, | ||||||
|  |     18874368, | ||||||
|  |     23068672, | ||||||
|  |     27262976, | ||||||
|  |     31457280, | ||||||
|  |     35651584, | ||||||
|  |     39845888, | ||||||
|  |     44040192, | ||||||
|  |     48234496, | ||||||
|  |     52428800, | ||||||
|  |   ]; | ||||||
|  | 
 | ||||||
|  |   FutureOr<void> launchBenchmark() async { | ||||||
|  |     emit(const BenchmarkState.loading()); | ||||||
|  | 
 | ||||||
|  |     final sk = await sessionRepository.getSessionKey(); | ||||||
|  | 
 | ||||||
|  |     if (sk.isErr) { | ||||||
|  |       await loggerRepository.addLog( | ||||||
|  |         const LogError('No SecretKey!\n' | ||||||
|  |             'Go in Key tab and generate or derive one.'), | ||||||
|  |       ); | ||||||
|  |       emit( | ||||||
|  |         BenchmarkState.failure( | ||||||
|  |           sk.err?.message, | ||||||
|  |         ), | ||||||
|  |       ); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     int run = 0; | ||||||
|  |     final csv = StringBuffer( | ||||||
|  |       'Run;Size (B);Encryption Time (ms);Decryption Time (ms)\n', | ||||||
|  |     ); | ||||||
|  |     for (final size in testedSizes) { | ||||||
|  |       run++; | ||||||
|  |       final StringBuffer csvLine = StringBuffer(); | ||||||
|  |       final dummyBytes = Uint8List(size); | ||||||
|  |       csvLine.write('$run;$size;'); | ||||||
|  | 
 | ||||||
|  |       // Encryption | ||||||
|  |       final beforeEncryption = DateTime.now(); | ||||||
|  | 
 | ||||||
|  |       final encryptedBigFileResult = await cryptoRepository.encrypt( | ||||||
|  |         dummyBytes, | ||||||
|  |         sk.ok!, | ||||||
|  |       ); | ||||||
|  | 
 | ||||||
|  |       final afterEncryption = DateTime.now(); | ||||||
|  | 
 | ||||||
|  |       final benchmarkEncryption = afterEncryption.millisecondsSinceEpoch - | ||||||
|  |           beforeEncryption.millisecondsSinceEpoch; | ||||||
|  | 
 | ||||||
|  |       await loggerRepository.addLog( | ||||||
|  |         LogInfo( | ||||||
|  |           '[Benchmark] ${size ~/ 1000000}MB => Encryption took $benchmarkEncryption ms', | ||||||
|  |         ), | ||||||
|  |       ); | ||||||
|  | 
 | ||||||
|  |       csvLine.write('$benchmarkEncryption'); | ||||||
|  | 
 | ||||||
|  |       if (encryptedBigFileResult.isErr) { | ||||||
|  |         await loggerRepository.addLog( | ||||||
|  |           LogError( | ||||||
|  |             'Encryption failed: ${encryptedBigFileResult.err?.message}', | ||||||
|  |           ), | ||||||
|  |         ); | ||||||
|  |         emit( | ||||||
|  |           BenchmarkState.failure( | ||||||
|  |             encryptedBigFileResult.err?.message, | ||||||
|  |           ), | ||||||
|  |         ); | ||||||
|  |         return; | ||||||
|  |       } | ||||||
|  | 
 | ||||||
|  |       // Decryption | ||||||
|  |       final beforeDecryption = DateTime.now(); | ||||||
|  |       await cryptoRepository.decrypt( | ||||||
|  |         encryptedBigFileResult.ok!, | ||||||
|  |         sk.ok!, | ||||||
|  |       ); | ||||||
|  |       final afterDecryption = DateTime.now(); | ||||||
|  |       final benchmarkDecryption = afterDecryption.millisecondsSinceEpoch - | ||||||
|  |           beforeDecryption.millisecondsSinceEpoch; | ||||||
|  |       await loggerRepository.addLog( | ||||||
|  |         LogInfo( | ||||||
|  |           '[Benchmark] ${size ~/ 1000000}MB => Decryption took $benchmarkDecryption ms', | ||||||
|  |         ), | ||||||
|  |       ); | ||||||
|  | 
 | ||||||
|  |       csvLine.write(';$benchmarkDecryption'); | ||||||
|  |       csv.writeln(csvLine); | ||||||
|  |     } | ||||||
|  |     debugPrint(csv.toString()); | ||||||
|  |     emit( | ||||||
|  |       const BenchmarkState.success(), | ||||||
|  |     ); | ||||||
|  | 
 | ||||||
|  |     return; | ||||||
|  |   } | ||||||
|  | } | ||||||
| @ -0,0 +1,27 @@ | |||||||
|  | // Copyright 2019-2023 Hugo Pointcheval | ||||||
|  | // | ||||||
|  | // Use of this source code is governed by an MIT-style | ||||||
|  | // license that can be found in the LICENSE file or at | ||||||
|  | // https://opensource.org/licenses/MIT. | ||||||
|  | 
 | ||||||
|  | part of 'benchmark_cubit.dart'; | ||||||
|  | 
 | ||||||
|  | @immutable | ||||||
|  | class BenchmarkState { | ||||||
|  |   const BenchmarkState.initial() | ||||||
|  |       : state = State.initial, | ||||||
|  |         error = null; | ||||||
|  | 
 | ||||||
|  |   const BenchmarkState.loading() | ||||||
|  |       : state = State.loading, | ||||||
|  |         error = null; | ||||||
|  | 
 | ||||||
|  |   const BenchmarkState.failure(this.error) : state = State.failure; | ||||||
|  | 
 | ||||||
|  |   const BenchmarkState.success() | ||||||
|  |       : state = State.success, | ||||||
|  |         error = null; | ||||||
|  | 
 | ||||||
|  |   final State state; | ||||||
|  |   final String? error; | ||||||
|  | } | ||||||
| @ -0,0 +1,55 @@ | |||||||
|  | // Copyright 2019-2023 Hugo Pointcheval | ||||||
|  | // | ||||||
|  | // Use of this source code is governed by an MIT-style | ||||||
|  | // license that can be found in the LICENSE file or at | ||||||
|  | // https://opensource.org/licenses/MIT. | ||||||
|  | 
 | ||||||
|  | import 'package:flutter/material.dart'; | ||||||
|  | import 'package:native_crypto_example/core/typography.dart'; | ||||||
|  | import 'package:native_crypto_example/domain/repositories/crypto_repository.dart'; | ||||||
|  | import 'package:native_crypto_example/domain/repositories/logger_repository.dart'; | ||||||
|  | import 'package:native_crypto_example/domain/repositories/session_repository.dart'; | ||||||
|  | import 'package:native_crypto_example/presentation/benchmark/blocs/benchmark_cubit.dart'; | ||||||
|  | import 'package:native_crypto_example/presentation/home/state_management/widgets/button_state_management.dart'; | ||||||
|  | import 'package:native_crypto_example/presentation/output/widgets/logs.dart'; | ||||||
|  | import 'package:wyatt_bloc_helper/wyatt_bloc_helper.dart'; | ||||||
|  | 
 | ||||||
|  | class BenchmarkStateManagement | ||||||
|  |     extends CubitScreen<BenchmarkCubit, BenchmarkState> { | ||||||
|  |   const BenchmarkStateManagement({super.key}); | ||||||
|  | 
 | ||||||
|  |   @override | ||||||
|  |   BenchmarkCubit create(BuildContext context) => BenchmarkCubit( | ||||||
|  |         sessionRepository: repo<SessionRepository>(context), | ||||||
|  |         loggerRepository: repo<LoggerRepository>(context), | ||||||
|  |         cryptoRepository: repo<CryptoRepository>(context), | ||||||
|  |       ); | ||||||
|  | 
 | ||||||
|  |   @override | ||||||
|  |   Widget onBuild(BuildContext context, BenchmarkState state) => ListView( | ||||||
|  |         children: [ | ||||||
|  |           const Logs(), | ||||||
|  |           const Padding( | ||||||
|  |             padding: EdgeInsets.all(8), | ||||||
|  |             child: Text( | ||||||
|  |               'Benchmark', | ||||||
|  |               style: AppTypography.title, | ||||||
|  |             ), | ||||||
|  |           ), | ||||||
|  |           const Padding( | ||||||
|  |             padding: EdgeInsets.all(8), | ||||||
|  |             child: Text( | ||||||
|  |               '''In computer science, a benchmark is a standardized way to measure the performance of a software program or hardware device. A benchmark is typically a set of tests or tasks designed to measure how quickly a program can complete a given set of operations or how efficiently a hardware device can perform a specific task.''', | ||||||
|  |               style: AppTypography.body, | ||||||
|  |             ), | ||||||
|  |           ), | ||||||
|  |           Padding( | ||||||
|  |             padding: const EdgeInsets.all(8), | ||||||
|  |             child: ButtonStateManagement( | ||||||
|  |               label: 'Launch', | ||||||
|  |               onPressed: () => bloc(context).launchBenchmark(), | ||||||
|  |             ), | ||||||
|  |           ), | ||||||
|  |         ], | ||||||
|  |       ); | ||||||
|  | } | ||||||
| @ -5,7 +5,9 @@ | |||||||
| // https://opensource.org/licenses/MIT. | // https://opensource.org/licenses/MIT. | ||||||
| 
 | 
 | ||||||
| import 'dart:async'; | import 'dart:async'; | ||||||
|  | import 'dart:io'; | ||||||
| 
 | 
 | ||||||
|  | import 'package:file_picker/file_picker.dart'; | ||||||
| import 'package:flutter/foundation.dart'; | import 'package:flutter/foundation.dart'; | ||||||
| import 'package:flutter_bloc/flutter_bloc.dart'; | import 'package:flutter_bloc/flutter_bloc.dart'; | ||||||
| import 'package:native_crypto/native_crypto.dart'; | import 'package:native_crypto/native_crypto.dart'; | ||||||
| @ -232,4 +234,184 @@ class AESCubit extends Cubit<AESState> { | |||||||
| 
 | 
 | ||||||
|     return; |     return; | ||||||
|   } |   } | ||||||
|  | 
 | ||||||
|  |   FutureOr<void> encryptFile() async { | ||||||
|  |     emit(state.copyWith(state: State.loading)); | ||||||
|  | 
 | ||||||
|  |     final sk = await sessionRepository.getSessionKey(); | ||||||
|  | 
 | ||||||
|  |     if (sk.isErr) { | ||||||
|  |       await loggerRepository.addLog( | ||||||
|  |         const LogError('No SecretKey!\n' | ||||||
|  |             'Go in Key tab and generate or derive one.'), | ||||||
|  |       ); | ||||||
|  |       emit( | ||||||
|  |         state.copyWith( | ||||||
|  |           state: State.failure, | ||||||
|  |           error: sk.err?.message, | ||||||
|  |         ), | ||||||
|  |       ); | ||||||
|  | 
 | ||||||
|  |       return; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     // Pick file to encrypt | ||||||
|  |     final pickFileResult = await FilePicker.platform.pickFiles(); | ||||||
|  | 
 | ||||||
|  |     if (pickFileResult == null) { | ||||||
|  |       await loggerRepository.addLog( | ||||||
|  |         const LogError('No file selected.'), | ||||||
|  |       ); | ||||||
|  |       emit( | ||||||
|  |         state.copyWith( | ||||||
|  |           state: State.failure, | ||||||
|  |           error: 'No file selected.', | ||||||
|  |         ), | ||||||
|  |       ); | ||||||
|  | 
 | ||||||
|  |       return; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     final file = File(pickFileResult.files.single.path!); | ||||||
|  | 
 | ||||||
|  |     // Pick folder to store the encrypted file | ||||||
|  |     final resultFolder = await FilePicker.platform.getDirectoryPath(); | ||||||
|  | 
 | ||||||
|  |     if (resultFolder == null) { | ||||||
|  |       await loggerRepository.addLog( | ||||||
|  |         const LogError('No folder selected.'), | ||||||
|  |       ); | ||||||
|  |       emit( | ||||||
|  |         state.copyWith( | ||||||
|  |           state: State.failure, | ||||||
|  |           error: 'No folder selected.', | ||||||
|  |         ), | ||||||
|  |       ); | ||||||
|  | 
 | ||||||
|  |       return; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     final folder = Directory(resultFolder); | ||||||
|  | 
 | ||||||
|  |     final encryption = await cryptoRepository.encryptFile( | ||||||
|  |       file, | ||||||
|  |       folder.uri, | ||||||
|  |       sk.ok!, | ||||||
|  |     ); | ||||||
|  | 
 | ||||||
|  |     emit( | ||||||
|  |       await encryption.foldAsync( | ||||||
|  |         (_) async { | ||||||
|  |           await loggerRepository.addLog( | ||||||
|  |             const LogInfo('File successfully encrypted.\n'), | ||||||
|  |           ); | ||||||
|  |           return state.copyWith( | ||||||
|  |             state: State.success, | ||||||
|  |             plainTextFile: '', | ||||||
|  |             cipherTextFile: '', | ||||||
|  |           ); | ||||||
|  |         }, | ||||||
|  |         (error) async { | ||||||
|  |           await loggerRepository.addLog( | ||||||
|  |             LogError(error.message ?? 'Error during encryption.'), | ||||||
|  |           ); | ||||||
|  |           return state.copyWith( | ||||||
|  |             state: State.failure, | ||||||
|  |             error: error.message, | ||||||
|  |           ); | ||||||
|  |         }, | ||||||
|  |       ), | ||||||
|  |     ); | ||||||
|  | 
 | ||||||
|  |     return; | ||||||
|  |   } | ||||||
|  | 
 | ||||||
|  |   FutureOr<void> decryptFile() async { | ||||||
|  |     emit(state.copyWith(state: State.loading)); | ||||||
|  | 
 | ||||||
|  |     final sk = await sessionRepository.getSessionKey(); | ||||||
|  | 
 | ||||||
|  |     if (sk.isErr) { | ||||||
|  |       await loggerRepository.addLog( | ||||||
|  |         const LogError('No SecretKey!\n' | ||||||
|  |             'Go in Key tab and generate or derive one.'), | ||||||
|  |       ); | ||||||
|  |       emit( | ||||||
|  |         state.copyWith( | ||||||
|  |           state: State.failure, | ||||||
|  |           error: sk.err?.message, | ||||||
|  |         ), | ||||||
|  |       ); | ||||||
|  | 
 | ||||||
|  |       return; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     await FilePicker.platform.clearTemporaryFiles(); | ||||||
|  | 
 | ||||||
|  |     final resultPickFile = await FilePicker.platform.pickFiles(); | ||||||
|  | 
 | ||||||
|  |     if (resultPickFile == null) { | ||||||
|  |       await loggerRepository.addLog( | ||||||
|  |         const LogError('No file selected.'), | ||||||
|  |       ); | ||||||
|  |       emit( | ||||||
|  |         state.copyWith( | ||||||
|  |           state: State.failure, | ||||||
|  |           error: 'No file selected.', | ||||||
|  |         ), | ||||||
|  |       ); | ||||||
|  | 
 | ||||||
|  |       return; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     final file = File(resultPickFile.files.single.path!); | ||||||
|  | 
 | ||||||
|  |     // Pick folder to store the encrypted file | ||||||
|  |     final resultFolder = await FilePicker.platform.getDirectoryPath(); | ||||||
|  | 
 | ||||||
|  |     if (resultFolder == null) { | ||||||
|  |       await loggerRepository.addLog( | ||||||
|  |         const LogError('No folder selected.'), | ||||||
|  |       ); | ||||||
|  |       emit( | ||||||
|  |         state.copyWith( | ||||||
|  |           state: State.failure, | ||||||
|  |           error: 'No folder selected.', | ||||||
|  |         ), | ||||||
|  |       ); | ||||||
|  | 
 | ||||||
|  |       return; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     final folder = Directory(resultFolder); | ||||||
|  | 
 | ||||||
|  |     final decryption = | ||||||
|  |         await cryptoRepository.decryptFile(file, folder.uri, sk.ok!); | ||||||
|  | 
 | ||||||
|  |     emit( | ||||||
|  |       await decryption.foldAsync( | ||||||
|  |         (_) async { | ||||||
|  |           await loggerRepository.addLog( | ||||||
|  |             const LogInfo('File successfully decrypted.\n'), | ||||||
|  |           ); | ||||||
|  |           return state.copyWith( | ||||||
|  |             state: State.success, | ||||||
|  |             plainTextFile: '', | ||||||
|  |             cipherTextFile: '', | ||||||
|  |           ); | ||||||
|  |         }, | ||||||
|  |         (error) async { | ||||||
|  |           await loggerRepository.addLog( | ||||||
|  |             LogError(error.message ?? 'Error during decryption.'), | ||||||
|  |           ); | ||||||
|  |           return state.copyWith( | ||||||
|  |             state: State.failure, | ||||||
|  |             error: error.message, | ||||||
|  |           ); | ||||||
|  |         }, | ||||||
|  |       ), | ||||||
|  |     ); | ||||||
|  | 
 | ||||||
|  |     return; | ||||||
|  |   } | ||||||
| } | } | ||||||
|  | |||||||
| @ -79,6 +79,27 @@ class AESStateManagement extends CubitScreen<AESCubit, AESState> { | |||||||
|               onPressed: () => bloc(context).decryptFromMemory(), |               onPressed: () => bloc(context).decryptFromMemory(), | ||||||
|             ), |             ), | ||||||
|           ), |           ), | ||||||
|  |           const Padding( | ||||||
|  |             padding: EdgeInsets.all(8), | ||||||
|  |             child: Text( | ||||||
|  |               'File', | ||||||
|  |               style: AppTypography.title, | ||||||
|  |             ), | ||||||
|  |           ), | ||||||
|  |           Padding( | ||||||
|  |             padding: const EdgeInsets.all(8), | ||||||
|  |             child: ButtonStateManagement( | ||||||
|  |               label: 'Encrypt file', | ||||||
|  |               onPressed: () => bloc(context).encryptFile(), | ||||||
|  |             ), | ||||||
|  |           ), | ||||||
|  |           Padding( | ||||||
|  |             padding: const EdgeInsets.all(8), | ||||||
|  |             child: ButtonStateManagement( | ||||||
|  |               label: 'Decrypt file', | ||||||
|  |               onPressed: () => bloc(context).decryptFile(), | ||||||
|  |             ), | ||||||
|  |           ), | ||||||
|           const Padding( |           const Padding( | ||||||
|             padding: EdgeInsets.all(8), |             padding: EdgeInsets.all(8), | ||||||
|             child: Text( |             child: Text( | ||||||
|  | |||||||
| @ -8,7 +8,9 @@ import 'dart:async'; | |||||||
| 
 | 
 | ||||||
| import 'package:flutter/foundation.dart'; | import 'package:flutter/foundation.dart'; | ||||||
| import 'package:flutter_bloc/flutter_bloc.dart'; | import 'package:flutter_bloc/flutter_bloc.dart'; | ||||||
|  | import 'package:native_crypto_example/data/repositories/crypto_repository_switchable_impl.dart'; | ||||||
| import 'package:native_crypto_example/domain/entities/mode.dart'; | import 'package:native_crypto_example/domain/entities/mode.dart'; | ||||||
|  | import 'package:native_crypto_example/domain/repositories/crypto_repository.dart'; | ||||||
| import 'package:native_crypto_example/domain/repositories/session_repository.dart'; | import 'package:native_crypto_example/domain/repositories/session_repository.dart'; | ||||||
| 
 | 
 | ||||||
| part 'mode_switcher_state.dart'; | part 'mode_switcher_state.dart'; | ||||||
| @ -16,8 +18,11 @@ part 'mode_switcher_state.dart'; | |||||||
| class ModeSwitcherCubit extends Cubit<ModeSwitcherState> { | class ModeSwitcherCubit extends Cubit<ModeSwitcherState> { | ||||||
|   ModeSwitcherCubit( |   ModeSwitcherCubit( | ||||||
|     this.sessionRepository, |     this.sessionRepository, | ||||||
|  |     this.cryptoRepository, | ||||||
|   ) : super(const ModeSwitcherState(NativeCryptoMode())); |   ) : super(const ModeSwitcherState(NativeCryptoMode())); | ||||||
|  | 
 | ||||||
|   SessionRepository sessionRepository; |   SessionRepository sessionRepository; | ||||||
|  |   CryptoRepository cryptoRepository; | ||||||
| 
 | 
 | ||||||
|   FutureOr<void> switchMode() async { |   FutureOr<void> switchMode() async { | ||||||
|     final currentMode = await sessionRepository.getCurrentMode(); |     final currentMode = await sessionRepository.getCurrentMode(); | ||||||
| @ -31,9 +36,16 @@ class ModeSwitcherCubit extends Cubit<ModeSwitcherState> { | |||||||
|       } |       } | ||||||
| 
 | 
 | ||||||
|       sessionRepository.setCurrentMode(newMode); |       sessionRepository.setCurrentMode(newMode); | ||||||
|  |       if (cryptoRepository is CryptoRepositorySwitchableImpl) { | ||||||
|  |         (cryptoRepository as CryptoRepositorySwitchableImpl).mode = newMode; | ||||||
|  |       } | ||||||
|     } else { |     } else { | ||||||
|       newMode = const NativeCryptoMode(); |       newMode = const NativeCryptoMode(); | ||||||
|       sessionRepository.setCurrentMode(newMode); |       sessionRepository.setCurrentMode(newMode); | ||||||
|  | 
 | ||||||
|  |       if (cryptoRepository is CryptoRepositorySwitchableImpl) { | ||||||
|  |         (cryptoRepository as CryptoRepositorySwitchableImpl).mode = newMode; | ||||||
|  |       } | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     emit(ModeSwitcherState(newMode)); |     emit(ModeSwitcherState(newMode)); | ||||||
|  | |||||||
| @ -5,12 +5,12 @@ | |||||||
| // https://opensource.org/licenses/MIT. | // https://opensource.org/licenses/MIT. | ||||||
| 
 | 
 | ||||||
| import 'package:flutter/material.dart'; | import 'package:flutter/material.dart'; | ||||||
|  | import 'package:native_crypto_example/presentation/benchmark/state_management/benchmark_state_management.dart'; | ||||||
| import 'package:native_crypto_example/presentation/cipher/state_management/aes_state_management.dart'; | import 'package:native_crypto_example/presentation/cipher/state_management/aes_state_management.dart'; | ||||||
| import 'package:native_crypto_example/presentation/hash/state_management/hash_state_management.dart'; | import 'package:native_crypto_example/presentation/hash/state_management/hash_state_management.dart'; | ||||||
| import 'package:native_crypto_example/presentation/home/blocs/navigation_bar/navigation_bar_cubit.dart'; | import 'package:native_crypto_example/presentation/home/blocs/navigation_bar/navigation_bar_cubit.dart'; | ||||||
| import 'package:native_crypto_example/presentation/home/state_management/widgets/app_bar_state_management.dart'; | import 'package:native_crypto_example/presentation/home/state_management/widgets/app_bar_state_management.dart'; | ||||||
| import 'package:native_crypto_example/presentation/home/state_management/widgets/bottom_navigation_bar_state_management.dart'; | import 'package:native_crypto_example/presentation/home/state_management/widgets/bottom_navigation_bar_state_management.dart'; | ||||||
| import 'package:native_crypto_example/presentation/home/widgets/blank.dart'; |  | ||||||
| import 'package:native_crypto_example/presentation/kdf/state_management/key_derivation_state_management.dart'; | import 'package:native_crypto_example/presentation/kdf/state_management/key_derivation_state_management.dart'; | ||||||
| import 'package:native_crypto_example/presentation/test_vectors/state_management/test_vectors_state_management.dart'; | import 'package:native_crypto_example/presentation/test_vectors/state_management/test_vectors_state_management.dart'; | ||||||
| import 'package:wyatt_bloc_helper/wyatt_bloc_helper.dart'; | import 'package:wyatt_bloc_helper/wyatt_bloc_helper.dart'; | ||||||
| @ -24,7 +24,7 @@ class HomeStateManagement | |||||||
|     HashStateManagement(), |     HashStateManagement(), | ||||||
|     AESStateManagement(), |     AESStateManagement(), | ||||||
|     TestVectorsStateManagement(), |     TestVectorsStateManagement(), | ||||||
|     const Blank() |     const BenchmarkStateManagement(), | ||||||
|   ]; |   ]; | ||||||
| 
 | 
 | ||||||
|   @override |   @override | ||||||
|  | |||||||
| @ -22,12 +22,12 @@ class AppBarStateManagement | |||||||
|               : 'PointyCastle', |               : 'PointyCastle', | ||||||
|         ), |         ), | ||||||
|         backgroundColor: state.currentMode.primaryColor, |         backgroundColor: state.currentMode.primaryColor, | ||||||
|         // TODO(hpcl): enable mode switcher |         actions: [ | ||||||
|         // actions: [ |           Switch( | ||||||
|         //   Switch( |             activeColor: Colors.white, | ||||||
|         //     value: state.currentMode == const NativeCryptoMode(), |             value: state.currentMode == const NativeCryptoMode(), | ||||||
|         //     onChanged: (_) => bloc(context).switchMode(), |             onChanged: (_) => bloc(context).switchMode(), | ||||||
|         //   ) |           ) | ||||||
|         // ], |         ], | ||||||
|       ); |       ); | ||||||
| } | } | ||||||
|  | |||||||
| @ -32,6 +32,7 @@ dependencies: | |||||||
|     hosted: https://git.wyatt-studio.fr/api/packages/Wyatt-FOSS/pub/ |     hosted: https://git.wyatt-studio.fr/api/packages/Wyatt-FOSS/pub/ | ||||||
|     version: 2.0.0 |     version: 2.0.0 | ||||||
|   get_it: ^7.2.0 |   get_it: ^7.2.0 | ||||||
|  |   file_picker: ^5.2.7 | ||||||
| 
 | 
 | ||||||
| dev_dependencies: | dev_dependencies: | ||||||
|   flutter_test: { sdk: flutter } |   flutter_test: { sdk: flutter } | ||||||
|  | |||||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user