feat(api): update example with benchmark + file encryption
This commit is contained in:
parent
0bf72447a0
commit
7c8f7206f0
@ -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