diff --git a/native_crypto/example/android/app/src/main/AndroidManifest.xml b/native_crypto/example/android/app/src/main/AndroidManifest.xml index aa8a66a..c55f004 100644 --- a/native_crypto/example/android/app/src/main/AndroidManifest.xml +++ b/native_crypto/example/android/app/src/main/AndroidManifest.xml @@ -3,7 +3,6 @@ _test(WidgetRef ref, Cipher cipher) async { + Session state = ref.read(sessionProvider.state).state; + + if (state.secretKey.bytes.isEmpty) { + benchmarkStatus + .print('No SecretKey!\nGo in Key tab and generate or derive one.'); + return; + } + + int size = 64; + benchmarkStatus.print("Benchmark Test\n"); + + // Encryption + var before = DateTime.now(); + var encryptedBigFile = await cipher.encrypt(Uint8List(size * 1000000)); + var after = DateTime.now(); + var benchmark = + after.millisecondsSinceEpoch - before.millisecondsSinceEpoch; + benchmarkStatus.append('[$size MB] Encryption took $benchmark ms\n'); + + // Decryption + var befored = DateTime.now(); + await cipher.decrypt(encryptedBigFile); + var afterd = DateTime.now(); + var benchmarkd = afterd.millisecondsSinceEpoch - befored.millisecondsSinceEpoch; + benchmarkStatus.append('[$size MB] Decryption took $benchmarkd ms\n'); + } + Future _benchmark(WidgetRef ref, Cipher cipher) async { Session state = ref.read(sessionProvider.state).state; @@ -39,13 +67,14 @@ class BenchmarkPage extends ConsumerWidget { var beforeBench = DateTime.now(); for (int size in testedSizes) { - var bigFile = Uint8List(size * 1000000); + var b = ByteData(size * 1000000); + //var bigFile = Uint8List.view(); csv += "${size * 1000000};"; var cryptoTime = 0; // Encryption var before = DateTime.now(); - var encryptedBigFile = await cipher.encrypt(bigFile); + var encryptedBigFile = await cipher.encrypt(b.buffer.asUint8List()); var after = DateTime.now(); var benchmark = @@ -122,6 +151,10 @@ class BenchmarkPage extends ConsumerWidget { () => _benchmark(ref, cipher), "Launch benchmark", ), + Button( + () => _test(ref, cipher), + "Test benchmark", + ), Button( _clear, "Clear", diff --git a/native_crypto_android/android/src/main/kotlin/fr/pointcheval/native_crypto_android/NativeCryptoAndroidPlugin.kt b/native_crypto_android/android/src/main/kotlin/fr/pointcheval/native_crypto_android/NativeCryptoAndroidPlugin.kt index 04270a8..e9c5219 100644 --- a/native_crypto_android/android/src/main/kotlin/fr/pointcheval/native_crypto_android/NativeCryptoAndroidPlugin.kt +++ b/native_crypto_android/android/src/main/kotlin/fr/pointcheval/native_crypto_android/NativeCryptoAndroidPlugin.kt @@ -18,53 +18,85 @@ class NativeCryptoAndroidPlugin: FlutterPlugin, MethodCallHandler { private lateinit var channel : MethodChannel override fun onAttachedToEngine(@NonNull flutterPluginBinding: FlutterPlugin.FlutterPluginBinding) { - channel = MethodChannel(flutterPluginBinding.binaryMessenger, "plugins.hugop.cl/native_crypto") + channel = MethodChannel(flutterPluginBinding.flutterEngine.dartExecutor, "plugins.hugop.cl/native_crypto") channel.setMethodCallHandler(this) } override fun onMethodCall(@NonNull call: MethodCall, @NonNull result: Result) { when (call.method) { "digest" -> { - val data : ByteArray? = call.argument("data") - val algorithm : String? = call.argument("algorithm") - // TODO(hpcl): check if algorithm is null - // TODO(hpcl): check if digest is null - result.success(Hash.digest(data, algorithm!!)) + if (!call.hasArgument("data")) result.error("DATA_NULL", null, null); + if (!call.hasArgument("algorithm")) result.error("ALGORITHM_NULL", null, null); + + val data : ByteArray = call.argument("data")!! + val algorithm : String = call.argument("algorithm")!! + + result.success(Hash.digest(data, algorithm)) } "generateSecretKey" -> { - val bitsCount : Int? = call.argument("bitsCount") - // TODO(hpcl): check null - result.success(Key.fromSecureRandom(bitsCount!!)) + if (!call.hasArgument("bitsCount")) result.error("SIZE_NULL", null, null); + + val bitsCount : Int = call.argument("bitsCount")!! + + result.success(Key.fromSecureRandom(bitsCount)) } "generateKeyPair" -> { result.notImplemented() } "pbkdf2" -> { - val password : String? = call.argument("password") - val salt : String? = call.argument("salt") - val keyBytesCount : Int? = call.argument("keyBytesCount") - val iterations : Int? = call.argument("iterations") - val algorithm : String? = call.argument("algorithm") - // TODO(hpcl): check null - result.success(Key.fromPBKDF2(password!!, salt!!, keyBytesCount!!, iterations!!, algorithm!!)) + if (!call.hasArgument("password")) result.error("PASSWORD_NULL", null, null); + if (!call.hasArgument("salt")) result.error("SALT_NULL", null, null); + if (!call.hasArgument("keyBytesCount")) result.error("SIZE_NULL", null, null); + if (!call.hasArgument("iterations")) result.error("ITERATIONS_NULL", null, null); + if (!call.hasArgument("algorithm")) result.error("ALGORITHM_NULL", null, null); + + val password : String = call.argument("password")!! + val salt : String = call.argument("salt")!! + val keyBytesCount : Int = call.argument("keyBytesCount")!! + val iterations : Int = call.argument("iterations")!! + val algorithm : String = call.argument("algorithm")!! + + result.success(Key.fromPBKDF2(password, salt, keyBytesCount, iterations, algorithm)) } "encrypt" -> { - val data : ByteArray? = call.argument("data") - val key : ByteArray? = call.argument("key") - val algorithm : String? = call.argument("algorithm") - // TODO(hpcl): check null - // TODO(hcpl): check algorithm - result.success(AESCipher().encrypt(data!!, key!!)) + if (!call.hasArgument("data")) result.error("DATA_NULL", null, null); + if (!call.hasArgument("key")) result.error("KEY_NULL", null, null); + if (!call.hasArgument("algorithm")) result.error("ALGORITHM_NULL", null, null); + + val data : ByteArray = call.argument("data")!! + val key : ByteArray = call.argument("key")!! + val algorithm : String = call.argument("algorithm")!! + + if (algorithm == "aes") { + result.success(AESCipher().encrypt(data, key)) + } } "decrypt" -> { - val data : ByteArray? = call.argument("data") - val key : ByteArray? = call.argument("key") - val algorithm : String? = call.argument("algorithm") - // TODO(hpcl): check null - // TODO(hcpl): check algorithm - result.success(AESCipher().decrypt(data!!, key!!)) + if (!call.hasArgument("data")) result.error("DATA_NULL", null, null); + if (!call.hasArgument("key")) result.error("KEY_NULL", null, null); + if (!call.hasArgument("algorithm")) result.error("ALGORITHM_NULL", null, null); + + val data : ByteArray = call.argument("data")!! + val key : ByteArray = call.argument("key")!! + val algorithm : String = call.argument("algorithm")!! + + if (algorithm == "aes") { + result.success(AESCipher().decrypt(data, key)) + } } "generateSharedSecretKey" -> { + if (!call.hasArgument("salt")) result.error("SALT_NULL", null, null); + if (!call.hasArgument("keyBytesCount")) result.error("SIZE_NULL", null, null); + if (!call.hasArgument("ephemeralPrivateKey")) result.error("PRIVATE_KEY_NULL", null, null); + if (!call.hasArgument("otherPublicKey")) result.error("PUBLIC_KEY_NULL", null, null); + if (!call.hasArgument("hkdfAlgorithm")) result.error("ALGORITHM_NULL", null, null); + + val salt : ByteArray = call.argument("salt")!! + val keyBytesCount : Int = call.argument("keyBytesCount")!! + val ephemeralPrivateKey : ByteArray = call.argument("ephemeralPrivateKey")!! + val otherPublicKey : ByteArray = call.argument("otherPublicKey")!! + val hkdfAlgorithm : String = call.argument("hkdfAlgorithm")!! + result.notImplemented() } else -> result.notImplemented()