From 6397e10c0521213d0ddecbc494bf1385ec848f04 Mon Sep 17 00:00:00 2001 From: Hugo Pointcheval Date: Tue, 24 May 2022 18:43:46 +0200 Subject: [PATCH] feat(example): add PointyCastle benchmark --- .../example/android/build.gradle | 4 +- .../gradle/wrapper/gradle-wrapper.properties | 2 +- .../example/lib/pages/benchmark_page.dart | 56 +++++-------- .../example/lib/pointycastle/aes_gcm.dart | 78 +++++++++++++++++++ packages/native_crypto/example/pubspec.yaml | 1 + 5 files changed, 102 insertions(+), 39 deletions(-) create mode 100644 packages/native_crypto/example/lib/pointycastle/aes_gcm.dart diff --git a/packages/native_crypto/example/android/build.gradle b/packages/native_crypto/example/android/build.gradle index 24047dc..3245887 100644 --- a/packages/native_crypto/example/android/build.gradle +++ b/packages/native_crypto/example/android/build.gradle @@ -1,12 +1,12 @@ buildscript { - ext.kotlin_version = '1.3.50' + ext.kotlin_version = "1.6.21" repositories { google() mavenCentral() } dependencies { - classpath 'com.android.tools.build:gradle:4.1.0' + classpath 'com.android.tools.build:gradle:7.2.0' classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version" } } diff --git a/packages/native_crypto/example/android/gradle/wrapper/gradle-wrapper.properties b/packages/native_crypto/example/android/gradle/wrapper/gradle-wrapper.properties index bc6a58a..562c5e4 100644 --- a/packages/native_crypto/example/android/gradle/wrapper/gradle-wrapper.properties +++ b/packages/native_crypto/example/android/gradle/wrapper/gradle-wrapper.properties @@ -3,4 +3,4 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-6.7-all.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-7.3.3-all.zip diff --git a/packages/native_crypto/example/lib/pages/benchmark_page.dart b/packages/native_crypto/example/lib/pages/benchmark_page.dart index 71c4bea..34e8ba0 100644 --- a/packages/native_crypto/example/lib/pages/benchmark_page.dart +++ b/packages/native_crypto/example/lib/pages/benchmark_page.dart @@ -3,7 +3,7 @@ // ----- // File: benchmark_page.dart // Created Date: 28/12/2021 15:12:39 -// Last Modified: 28/12/2021 17:01:41 +// Last Modified: 24/05/2022 17:23:33 // ----- // Copyright (c) 2021 @@ -12,6 +12,7 @@ import 'dart:typed_data'; import 'package:flutter/material.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart'; import 'package:native_crypto/native_crypto.dart'; +import 'package:native_crypto_example/pointycastle/aes_gcm.dart'; import 'package:native_crypto_example/widgets/button.dart'; import '../session.dart'; @@ -23,37 +24,10 @@ class BenchmarkPage extends ConsumerWidget { final Output keyContent = Output(); final Output benchmarkStatus = Output(large: true); - Future _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 { + Future _benchmark(WidgetRef ref, Cipher cipher, + {bool usePc = false}) async { Session state = ref.read(sessionProvider.state).state; + AesGcm pc = AesGcm(); if (state.secretKey.bytes.isEmpty) { benchmarkStatus @@ -75,7 +49,13 @@ class BenchmarkPage extends ConsumerWidget { // Encryption var before = DateTime.now(); - var encryptedBigFile = await cipher.encrypt(b.buffer.asUint8List()); + Object encryptedBigFile; + if (usePc) { + encryptedBigFile = + pc.encrypt(b.buffer.asUint8List(), state.secretKey.bytes); + } else { + encryptedBigFile = await cipher.encrypt(b.buffer.asUint8List()); + } var after = DateTime.now(); var benchmark = @@ -87,7 +67,11 @@ class BenchmarkPage extends ConsumerWidget { // Decryption before = DateTime.now(); - await cipher.decrypt(encryptedBigFile); + if (usePc) { + pc.decrypt(encryptedBigFile as Uint8List, state.secretKey.bytes); + } else { + await cipher.decrypt(encryptedBigFile as CipherText); + } after = DateTime.now(); benchmark = after.millisecondsSinceEpoch - before.millisecondsSinceEpoch; @@ -150,11 +134,11 @@ class BenchmarkPage extends ConsumerWidget { children: [ Button( () => _benchmark(ref, cipher), - "Launch benchmark", + "NativeCrypto", ), Button( - () => _test(ref, cipher), - "Test benchmark", + () => _benchmark(ref, cipher, usePc: true), + "PointyCastle", ), Button( _clear, diff --git a/packages/native_crypto/example/lib/pointycastle/aes_gcm.dart b/packages/native_crypto/example/lib/pointycastle/aes_gcm.dart new file mode 100644 index 0000000..a0aa0be --- /dev/null +++ b/packages/native_crypto/example/lib/pointycastle/aes_gcm.dart @@ -0,0 +1,78 @@ +// Author: Hugo Pointcheval +// Email: git@pcl.ovh +// ----- +// File: aes_gcm.dart +// Created Date: 24/05/2022 16:34:54 +// Last Modified: 24/05/2022 17:15:22 +// ----- +// Copyright (c) 2022 + +import 'dart:typed_data'; + +import 'package:pointycastle/export.dart'; +import 'package:pointycastle/src/platform_check/platform_check.dart'; + +class AesGcm { + FortunaRandom? _secureRandom; + + Uint8List encrypt(Uint8List data, Uint8List key) { + final iv = generateRandomBytes(12); + + final gcm = GCMBlockCipher(AESEngine()) + ..init( + true, + AEADParameters( + KeyParameter(key), + 16 * 8, + iv!, + Uint8List(0), + ), + ); // true=encrypt + + final cipherText = gcm.process(data); + + return Uint8List.fromList( + iv + cipherText, + ); + } + + Uint8List decrypt(Uint8List cipherText, Uint8List key) { + final iv = Uint8List.fromList(cipherText.sublist(0, 12)); + final cipherTextWithoutIv = Uint8List.fromList( + cipherText.sublist(12), + ); + + final gcm = GCMBlockCipher(AESEngine()) + ..init( + false, + AEADParameters( + KeyParameter(key), + 16 * 8, + iv, + Uint8List(0), + ), + ); // false=decrypt + + // Decrypt the cipherText block-by-block + + final paddedPlainText = gcm.process(cipherTextWithoutIv); + + return paddedPlainText; + } + + /// Generate random bytes to use as the Initialization Vector (IV). + Uint8List? generateRandomBytes(int numBytes) { + if (_secureRandom == null) { + // First invocation: create _secureRandom and seed it + + _secureRandom = FortunaRandom(); + _secureRandom!.seed( + KeyParameter(Platform.instance.platformEntropySource().getBytes(32))); + } + + // Use it to generate the random bytes + + final iv = _secureRandom!.nextBytes(numBytes); + return iv; + } +} diff --git a/packages/native_crypto/example/pubspec.yaml b/packages/native_crypto/example/pubspec.yaml index b8fd86e..7fb09c7 100644 --- a/packages/native_crypto/example/pubspec.yaml +++ b/packages/native_crypto/example/pubspec.yaml @@ -30,6 +30,7 @@ dependencies: # Use with the CupertinoIcons class for iOS style icons. cupertino_icons: ^1.0.2 flutter_riverpod: ^1.0.3 + pointycastle: ^3.6.0 dev_dependencies: flutter_test: