diff --git a/.drone.yml b/.drone.yml
new file mode 100644
index 0000000..74ade5c
--- /dev/null
+++ b/.drone.yml
@@ -0,0 +1,17 @@
+kind: pipeline
+type: docker
+name: default
+
+steps:
+- name: test:all
+ image: cirrusci/flutter:stable
+ commands:
+ - PATH=$PATH:$HOME/.pub-cache/bin
+ - flutter doctor
+ - flutter pub global activate melos
+ - melos bs
+ - melos run test:all
+
+trigger:
+ branch:
+ - master
\ No newline at end of file
diff --git a/native_crypto/.gitignore b/.gitignore
similarity index 74%
rename from native_crypto/.gitignore
rename to .gitignore
index 9a04984..4c39101 100644
--- a/native_crypto/.gitignore
+++ b/.gitignore
@@ -1,7 +1,7 @@
# File created using '.gitignore Generator' for Visual Studio Code: https://bit.ly/vscode-gig
-# Created by https://www.toptal.com/developers/gitignore/api/visualstudiocode,macos,dart,flutter,intellij+all,kotlin,linux,swift,windows
-# Edit at https://www.toptal.com/developers/gitignore?templates=visualstudiocode,macos,dart,flutter,intellij+all,kotlin,linux,swift,windows
+# Created by https://www.toptal.com/developers/gitignore/api/visualstudiocode,macos,dart,flutter,java,jetbrains+all,kotlin,linux,objective-c,rust,swift,windows,xcode
+# Edit at https://www.toptal.com/developers/gitignore?templates=visualstudiocode,macos,dart,flutter,java,jetbrains+all,kotlin,linux,objective-c,rust,swift,windows,xcode
### Dart ###
# See https://www.dartlang.org/guides/libraries/private-files
@@ -95,7 +95,33 @@ lib/generated_plugin_registrant.dart
!**/ios/**/default.perspectivev3
!/packages/flutter_tools/test/data/dart_dependencies_test/**/.packages
-### Intellij+all ###
+### Java ###
+# Compiled class file
+*.class
+
+# Log file
+*.log
+
+# BlueJ files
+*.ctxt
+
+# Mobile Tools for Java (J2ME)
+.mtj.tmp/
+
+# Package Files #
+*.jar
+*.war
+*.nar
+*.ear
+*.zip
+*.tar.gz
+*.rar
+
+# virtual machine crash logs, see http://www.java.com/en/download/help/error_hotspot.xml
+hs_err_pid*
+replay_pid*
+
+### JetBrains+all ###
# Covers JetBrains IDEs: IntelliJ, RubyMine, PhpStorm, AppCode, PyCharm, CLion, Android Studio, WebStorm and Rider
# Reference: https://intellij-support.jetbrains.com/hc/en-us/articles/206544839
@@ -159,6 +185,9 @@ atlassian-ide-plugin.xml
# Cursive Clojure plugin
.idea/replstate.xml
+# SonarLint plugin
+.idea/sonarlint/
+
# Crashlytics plugin (for Android Studio and IntelliJ)
com_crashlytics_export_strings.xml
crashlytics.properties
@@ -171,46 +200,27 @@ fabric.properties
# Android studio 3.1+ serialized cache file
.idea/caches/build_file_checksums.ser
-### Intellij+all Patch ###
-# Ignores the whole .idea folder and all .iml files
-# See https://github.com/joeblau/gitignore.io/issues/186 and https://github.com/joeblau/gitignore.io/issues/360
-
-.idea/
-
-# Reason: https://github.com/joeblau/gitignore.io/issues/186#issuecomment-249601023
+### JetBrains+all Patch ###
+# Ignore everything but code style settings and run configurations
+# that are supposed to be shared within teams.
-*.iml
-modules.xml
-.idea/misc.xml
-*.ipr
+.idea/*
-# Sonarlint plugin
-.idea/sonarlint
+!.idea/codeStyles
+!.idea/runConfigurations
### Kotlin ###
# Compiled class file
-*.class
# Log file
-*.log
# BlueJ files
-*.ctxt
# Mobile Tools for Java (J2ME)
-.mtj.tmp/
# Package Files #
-*.jar
-*.war
-*.nar
-*.ear
-*.zip
-*.tar.gz
-*.rar
# virtual machine crash logs, see http://www.java.com/en/download/help/error_hotspot.xml
-hs_err_pid*
### Linux ###
*~
@@ -234,7 +244,8 @@ hs_err_pid*
.LSOverride
# Icon must end with two \r
-Icon
+Icon
+
# Thumbnails
._*
@@ -255,7 +266,11 @@ Network Trash Folder
Temporary Items
.apdisk
-### Swift ###
+### macOS Patch ###
+# iCloud generated files
+*.icloud
+
+### Objective-C ###
# Xcode
#
# gitignore contributors: remember to update Global/Xcode.gitignore, Objective-C.gitignore & Swift.gitignore
@@ -287,6 +302,64 @@ DerivedData/
*.dSYM.zip
*.dSYM
+# CocoaPods
+# We recommend against adding the Pods directory to your .gitignore. However
+# you should judge for yourself, the pros and cons are mentioned at:
+# https://guides.cocoapods.org/using/using-cocoapods.html#should-i-check-the-pods-directory-into-source-control
+# Pods/
+# Add this line if you want to avoid checking in source code from the Xcode workspace
+# *.xcworkspace
+
+# Carthage
+# Add this line if you want to avoid checking in source code from Carthage dependencies.
+# Carthage/Checkouts
+
+Carthage/Build/
+
+# fastlane
+# It is recommended to not store the screenshots in the git repo.
+# Instead, use fastlane to re-generate the screenshots whenever they are needed.
+# For more information about the recommended setup visit:
+# https://docs.fastlane.tools/best-practices/source-control/#source-control
+
+fastlane/report.xml
+fastlane/Preview.html
+fastlane/screenshots/**/*.png
+fastlane/test_output
+
+# Code Injection
+# After new code Injection tools there's a generated folder /iOSInjectionProject
+# https://github.com/johnno1962/injectionforxcode
+
+iOSInjectionProject/
+
+### Objective-C Patch ###
+
+### Rust ###
+# Generated by Cargo
+# will have compiled files and executables
+debug/
+target/
+
+# Remove Cargo.lock from gitignore if creating an executable, leave it for libraries
+# More information here https://doc.rust-lang.org/cargo/guide/cargo-toml-vs-cargo-lock.html
+Cargo.lock
+
+# These are backup files generated by rustfmt
+**/*.rs.bk
+
+# MSVC Windows builds of rustc generate these, which store debugging information
+*.pdb
+
+### Swift ###
+# Xcode
+# gitignore contributors: remember to update Global/Xcode.gitignore, Objective-C.gitignore & Swift.gitignore
+
+
+
+
+
+
## Playgrounds
timeline.xctimeline
playground.xcworkspace
@@ -315,7 +388,6 @@ playground.xcworkspace
# Add this line if you want to avoid checking in source code from Carthage dependencies.
# Carthage/Checkouts
-Carthage/Build/
# Accio dependency management
Dependencies/
@@ -327,16 +399,11 @@ Dependencies/
# For more information about the recommended setup visit:
# https://docs.fastlane.tools/best-practices/source-control/#source-control
-fastlane/report.xml
-fastlane/Preview.html
-fastlane/screenshots/**/*.png
-fastlane/test_output
# Code Injection
# After new code Injection tools there's a generated folder /iOSInjectionProject
# https://github.com/johnno1962/injectionforxcode
-iOSInjectionProject/
### VisualStudioCode ###
.vscode/*
@@ -344,18 +411,24 @@ iOSInjectionProject/
!.vscode/tasks.json
!.vscode/launch.json
!.vscode/extensions.json
-*.code-workspace
+!.vscode/*.code-snippets
# Local History for Visual Studio Code
.history/
+# Built Visual Studio Code Extensions
+*.vsix
+
### VisualStudioCode Patch ###
# Ignore all local history of files
.history
.ionide
# Support for Project snippet scope
-!.vscode/*.code-snippets
+.vscode/*.code-snippets
+
+# Ignore code-workspaces
+*.code-workspace
### Windows ###
# Windows thumbnail cache files
@@ -383,7 +456,27 @@ $RECYCLE.BIN/
# Windows shortcuts
*.lnk
-# End of https://www.toptal.com/developers/gitignore/api/visualstudiocode,macos,dart,flutter,intellij+all,kotlin,linux,swift,windows
+### Xcode ###
+
+## Xcode 8 and earlier
+
+### Xcode Patch ###
+*.xcodeproj/*
+!*.xcodeproj/project.pbxproj
+!*.xcodeproj/xcshareddata/
+!*.xcworkspace/contents.xcworkspacedata
+/*.gcno
+**/xcshareddata/WorkspaceSettings.xcsettings
+
+# End of https://www.toptal.com/developers/gitignore/api/visualstudiocode,macos,dart,flutter,java,jetbrains+all,kotlin,linux,objective-c,rust,swift,windows,xcode
# Custom rules (everything added below won't be overriden by 'Generate .gitignore File' if you use 'Update' option)
+# IntelliJ
+*.iml
+*.ipr
+*.iws
+.idea/
+
+# Mac
+.DS_Store
\ No newline at end of file
diff --git a/.vscode/launch.json b/.vscode/launch.json
new file mode 100644
index 0000000..d9becfd
--- /dev/null
+++ b/.vscode/launch.json
@@ -0,0 +1,28 @@
+{
+ // Use IntelliSense to learn about possible attributes.
+ // Hover to view descriptions of existing attributes.
+ // For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387
+ "version": "0.2.0",
+ "configurations": [
+ {
+ "name": "native_crypto",
+ "cwd": "packages/native_crypto/example",
+ "request": "launch",
+ "type": "dart"
+ },
+ {
+ "name": "native_crypto (profile mode)",
+ "cwd": "packages/native_crypto/example",
+ "request": "launch",
+ "type": "dart",
+ "flutterMode": "profile"
+ },
+ {
+ "name": "native_crypto (release mode)",
+ "cwd": "packages/native_crypto/example",
+ "request": "launch",
+ "type": "dart",
+ "flutterMode": "release"
+ },
+ ]
+}
\ No newline at end of file
diff --git a/AUTHORS b/AUTHORS
new file mode 100644
index 0000000..d9808a7
--- /dev/null
+++ b/AUTHORS
@@ -0,0 +1,6 @@
+# Below is a list of people and organizations that have contributed
+# to this project. Names should be added to the list like so:
+#
+# Name/Organization
+
+Hugo Pointcheval
\ No newline at end of file
diff --git a/CHANGELOG.md b/CHANGELOG.md
new file mode 100644
index 0000000..e4d77c8
--- /dev/null
+++ b/CHANGELOG.md
@@ -0,0 +1,66 @@
+# Change Log
+
+All notable changes to this project will be documented in this file.
+See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
+
+## 2022-05-25
+
+### Changes
+
+---
+
+Packages with breaking changes:
+
+ - There are no breaking changes in this release.
+
+Packages with other changes:
+
+ - [`native_crypto` - `v0.1.1`](#native_crypto---v011)
+
+---
+
+#### `native_crypto` - `v0.1.1`
+
+ - **REFACTOR**: change file organization.
+ - **PERF**: x10 perfomance improvement on android with better list management.
+ - **FIX**: benchmark output.
+ - **FIX**: update and fix code.
+ - **FEAT**: export new exceptions.
+ - **FEAT**: add PointyCastle benchmark.
+ - **DOCS**: add link to readme file.
+
+
+## 2022-05-25
+
+### Changes
+
+---
+
+Packages with breaking changes:
+
+ - There are no breaking changes in this release.
+
+Packages with other changes:
+
+ - [`native_crypto_ios` - `v0.1.1`](#native_crypto_ios---v011)
+ - [`native_crypto_android` - `v0.1.1`](#native_crypto_android---v011)
+ - [`native_crypto_platform_interface` - `v0.1.1`](#native_crypto_platform_interface---v011)
+
+---
+
+#### `native_crypto_ios` - `v0.1.1`
+
+ - **REFACTOR**: rework swift part.
+ - **PERF**: optimize swift code.
+
+#### `native_crypto_android` - `v0.1.1`
+
+ - **REFACTOR**: clean and modernize kotlin code.
+ - **PERF**: x10 perfomance improvement on android with better list management.
+ - **FEAT**: export new exceptions.
+
+#### `native_crypto_platform_interface` - `v0.1.1`
+
+ - **PERF**: x10 perfomance improvement on android with better list management.
+ - **FEAT**: export new exceptions.
+
diff --git a/LICENSE b/LICENSE
new file mode 100644
index 0000000..2f00d5b
--- /dev/null
+++ b/LICENSE
@@ -0,0 +1,21 @@
+MIT License
+
+Copyright (c) 2022 Hugo Pointcheval
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.
\ No newline at end of file
diff --git a/README.md b/README.md
new file mode 100644
index 0000000..507b7ec
--- /dev/null
+++ b/README.md
@@ -0,0 +1,133 @@
+
+
+
Fast and powerful cryptographic functions for Flutter.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+---
+
+[[Changelog]](./CHANGELOG.md) | [[License]](./LICENSE)
+
+---
+
+## About
+
+The goal of this plugin is to provide a fast and powerful cryptographic functions by calling native libraries. On Android, it uses [javax.cypto](https://developer.android.com/reference/javax/crypto/package-summary), and on iOS, it uses [CommonCrypto](https://opensource.apple.com/source/CommonCrypto/) and [CryptoKit](https://developer.apple.com/documentation/cryptokit/)
+
+I started this projet because I wanted to add cryptographic functions on a Flutter app. But I faced a problem with the well-known [Pointy Castle](https://pub.dev/packages/pointycastle) library: the performance was very poor. Here some benchmarks and comparison:
+
+![](resources/benchmarks.png)
+
+For comparison, on a *iPhone 13*, you can encrypt/decrypt a message of **2MiB** in **~5.6s** with PointyCastle and in **~40ms** with NativeCrypto. And on an *OnePlus 5*, you can encrypt/decrypt a message of **50MiB** in **~6min30** with PointyCastle and in less than **~1s** with NativeCrypto.
+
+In short, NativeCrypto is incomparable with PointyCastle.
+
+## Usage
+
+First, check compatibility with your targets.
+
+| iOS | Android | MacOS | Linux | Windows | Web |
+| --- | ------- | ----- | ----- | ------- | --- |
+| ✅ | ✅ | ❌ | ❌ | ❌ | ❌ |
+
+#### Hash
+
+To digest a message, you can use the following function:
+
+```dart
+Uint8List hash = await HashAlgorithm.sha256.digest(message);
+```
+
+> In NativeCrypto, you can use the following hash functions: SHA-256, SHA-384, SHA-512
+
+#### Keys
+
+You can build a `SecretKey` from a utf8, base64, base16 (hex) strings or raw bytes. You can also generate a SecretKey from secure random.
+
+```dart
+SecretKey secretKey = SecretKey(Uint8List.fromList([0x73, 0x65, 0x63, 0x72, 0x65, 0x74]));
+SecretKey secretKey = SecretKey.fromUtf8('secret');
+SecretKey secretKey = SecretKey.fromBase64('c2VjcmV0');
+SecretKey secretKey = SecretKey.fromBase16('63657274');
+SecretKey secretKey = await SecretKey.fromSecureRandom(256);
+```
+
+#### Key derivation
+
+You can derive a `SecretKey` using **PBKDF2**.
+
+First, you need to initialize a `Pbkdf2` object.
+
+```dart
+Pbkdf2 pbkdf2 = Pbkdf2(
+ keyBytesCount: 32,
+ iterations: 1000,
+ algorithm: HashAlgorithm.sha512,
+);
+```
+
+Then, you can derive a `SecretKey` from a password and salt.
+
+```dart
+SecretKey secretKey = await pbkdf2.derive(password: password, salt: 'salt');
+```
+
+> In NativeCrypto, you can use the following key derivation function: PBKDF2
+
+#### Cipher
+
+And now, you can use the `SecretKey` to encrypt/decrypt a message.
+
+First, you need to initialize a `Cipher` object.
+
+```dart
+AES cipher = AES(secretKey);
+```
+
+Then, you can encrypt your message.
+
+```dart
+CipherTextWrapper wrapper = await cipher.encrypt(message);
+
+CipherText cipherText = wrapper.unwrap();
+// same as
+CipherText cipherText = wrapper.single;
+
+// or
+
+List cipherTexts = wrapper.unwrap>();
+// same as
+List cipherTexts = wrapper.list;
+```
+
+After an encryption you obtain a `CipherTextWrapper` which contains `CipherText` or `List` depending on the message size. It's up to you to know how to unwrap the `CipherTextWrapper` depending the chunk size you configured.
+
+Uppon receiving encrypted message, you can decrypt it.
+You have to reconstruct the wrapper before decrypting.
+
+```dart
+CipherTextWrapper wrapper = CipherTextWrapper.fromBytes(
+ data,
+ ivLength: AESMode.gcm.ivLength,
+ tagLength: AESMode.gcm.tagLength,
+);
+```
+
+Then, you can decrypt your message.
+
+```dart
+Uint8List message = await cipher.decrypt(wrapper);
+```
\ No newline at end of file
diff --git a/melos.yaml b/melos.yaml
new file mode 100644
index 0000000..a311fc5
--- /dev/null
+++ b/melos.yaml
@@ -0,0 +1,57 @@
+name: NativeCrypto
+# repository: https://git.pointcheval.fr/NativeCrypto/native-crypto-flutter
+
+packages:
+ - packages/**
+
+command:
+ version:
+ updateGitTagRefs: true
+ linkToCommits: false # Gitea not support this
+ workspaceChangelog: true
+ # branch: master
+
+scripts:
+ lint:all:
+ run: melos run analyze && melos run format
+ description: Run all static analysis checks.
+
+ test:all:
+ run: |
+ melos run test --no-select
+ description: |
+ Run all tests available.
+
+ test:
+ run: |
+ melos exec -c 6 --fail-fast -- \
+ "flutter test --no-pub --no-test-assets"
+ description: Run `flutter test` for a specific package.
+ select-package:
+ dir-exists:
+ - test
+ ignore:
+ - "*web*"
+ - "*example*"
+
+ analyze:
+ run: |
+ melos exec -c 10 -- \
+ flutter analyze --fatal-infos
+ description: Run `flutter analyze` for all packages.
+
+ format:
+ run: melos exec flutter format . --fix
+ description: Run `flutter format` for all packages.
+
+ format-check:
+ run: melos exec flutter format . --set-exit-if-changed
+ description: Run `flutter format` checks for all packages.
+
+ clean:deep:
+ run: git clean -x -d -f -q
+ description: Clean things very deeply with `git clean`.
+
+ # Additional cleanup lifecycle script, executed when `melos clean` is run.
+ postclean: >
+ melos exec -c 6 -- "flutter clean"
\ No newline at end of file
diff --git a/native_crypto/CHANGELOG.md b/native_crypto/CHANGELOG.md
deleted file mode 100644
index 41cc7d8..0000000
--- a/native_crypto/CHANGELOG.md
+++ /dev/null
@@ -1,3 +0,0 @@
-## 0.0.1
-
-* TODO: Describe initial release.
diff --git a/native_crypto/LICENSE b/native_crypto/LICENSE
deleted file mode 100644
index ba75c69..0000000
--- a/native_crypto/LICENSE
+++ /dev/null
@@ -1 +0,0 @@
-TODO: Add your license here.
diff --git a/native_crypto/README.md b/native_crypto/README.md
deleted file mode 100644
index 1bf39c0..0000000
--- a/native_crypto/README.md
+++ /dev/null
@@ -1,18 +0,0 @@
-# native_crypto
-
-A new flutter plugin project.
-
-## Getting Started
-
-This project is a starting point for a Flutter
-[plug-in package](https://flutter.dev/developing-packages/),
-a specialized package that includes platform-specific implementation code for
-Android and/or iOS.
-
-For help getting started with Flutter, view our
-[online documentation](https://flutter.dev/docs), which offers tutorials,
-samples, guidance on mobile development, and a full API reference.
-
-The plugin project was generated without specifying the `--platforms` flag, no platforms are currently supported.
-To add platforms, run `flutter create -t plugin --platforms .` under the same
-directory. You can also find a detailed instruction on how to add platforms in the `pubspec.yaml` at https://flutter.dev/docs/development/packages-and-plugins/developing-packages#plugin-platforms.
diff --git a/native_crypto/analysis_options.yaml b/native_crypto/analysis_options.yaml
deleted file mode 100644
index a5744c1..0000000
--- a/native_crypto/analysis_options.yaml
+++ /dev/null
@@ -1,4 +0,0 @@
-include: package:flutter_lints/flutter.yaml
-
-# Additional information about this file can be found at
-# https://dart.dev/guides/language/analysis-options
diff --git a/native_crypto/example/ios/Runner.xcodeproj/project.pbxproj b/native_crypto/example/ios/Runner.xcodeproj/project.pbxproj
deleted file mode 100644
index 6571d99..0000000
--- a/native_crypto/example/ios/Runner.xcodeproj/project.pbxproj
+++ /dev/null
@@ -1,484 +0,0 @@
-// !$*UTF8*$!
-{
- archiveVersion = 1;
- classes = {
- };
- objectVersion = 50;
- objects = {
-
-/* Begin PBXBuildFile section */
- 1498D2341E8E89220040F4C2 /* GeneratedPluginRegistrant.m in Sources */ = {isa = PBXBuildFile; fileRef = 1498D2331E8E89220040F4C2 /* GeneratedPluginRegistrant.m */; };
- 3B3967161E833CAA004F5970 /* AppFrameworkInfo.plist in Resources */ = {isa = PBXBuildFile; fileRef = 3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */; };
- 74858FAF1ED2DC5600515810 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 74858FAE1ED2DC5600515810 /* AppDelegate.swift */; };
- 97C146FC1CF9000F007C117D /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FA1CF9000F007C117D /* Main.storyboard */; };
- 97C146FE1CF9000F007C117D /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FD1CF9000F007C117D /* Assets.xcassets */; };
- 97C147011CF9000F007C117D /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FF1CF9000F007C117D /* LaunchScreen.storyboard */; };
-/* End PBXBuildFile section */
-
-/* Begin PBXCopyFilesBuildPhase section */
- 9705A1C41CF9048500538489 /* Embed Frameworks */ = {
- isa = PBXCopyFilesBuildPhase;
- buildActionMask = 2147483647;
- dstPath = "";
- dstSubfolderSpec = 10;
- files = (
- );
- name = "Embed Frameworks";
- runOnlyForDeploymentPostprocessing = 0;
- };
-/* End PBXCopyFilesBuildPhase section */
-
-/* Begin PBXFileReference section */
- 1498D2321E8E86230040F4C2 /* GeneratedPluginRegistrant.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = GeneratedPluginRegistrant.h; sourceTree = ""; };
- 1498D2331E8E89220040F4C2 /* GeneratedPluginRegistrant.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GeneratedPluginRegistrant.m; sourceTree = ""; };
- 3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; name = AppFrameworkInfo.plist; path = Flutter/AppFrameworkInfo.plist; sourceTree = ""; };
- 74858FAD1ED2DC5600515810 /* Runner-Bridging-Header.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "Runner-Bridging-Header.h"; sourceTree = ""; };
- 74858FAE1ED2DC5600515810 /* AppDelegate.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = ""; };
- 7AFA3C8E1D35360C0083082E /* Release.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; name = Release.xcconfig; path = Flutter/Release.xcconfig; sourceTree = ""; };
- 9740EEB21CF90195004384FC /* Debug.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; name = Debug.xcconfig; path = Flutter/Debug.xcconfig; sourceTree = ""; };
- 9740EEB31CF90195004384FC /* Generated.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; name = Generated.xcconfig; path = Flutter/Generated.xcconfig; sourceTree = ""; };
- 97C146EE1CF9000F007C117D /* Runner.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = Runner.app; sourceTree = BUILT_PRODUCTS_DIR; };
- 97C146FB1CF9000F007C117D /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Main.storyboard; sourceTree = ""; };
- 97C146FD1CF9000F007C117D /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = ""; };
- 97C147001CF9000F007C117D /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/LaunchScreen.storyboard; sourceTree = ""; };
- 97C147021CF9000F007C117D /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; };
-/* End PBXFileReference section */
-
-/* Begin PBXFrameworksBuildPhase section */
- 97C146EB1CF9000F007C117D /* Frameworks */ = {
- isa = PBXFrameworksBuildPhase;
- buildActionMask = 2147483647;
- files = (
- );
- runOnlyForDeploymentPostprocessing = 0;
- };
-/* End PBXFrameworksBuildPhase section */
-
-/* Begin PBXGroup section */
- 9740EEB11CF90186004384FC /* Flutter */ = {
- isa = PBXGroup;
- children = (
- 3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */,
- 9740EEB21CF90195004384FC /* Debug.xcconfig */,
- 7AFA3C8E1D35360C0083082E /* Release.xcconfig */,
- 9740EEB31CF90195004384FC /* Generated.xcconfig */,
- );
- name = Flutter;
- sourceTree = "";
- };
- 97C146E51CF9000F007C117D = {
- isa = PBXGroup;
- children = (
- 9740EEB11CF90186004384FC /* Flutter */,
- 97C146F01CF9000F007C117D /* Runner */,
- 97C146EF1CF9000F007C117D /* Products */,
- );
- sourceTree = "";
- };
- 97C146EF1CF9000F007C117D /* Products */ = {
- isa = PBXGroup;
- children = (
- 97C146EE1CF9000F007C117D /* Runner.app */,
- );
- name = Products;
- sourceTree = "";
- };
- 97C146F01CF9000F007C117D /* Runner */ = {
- isa = PBXGroup;
- children = (
- 97C146FA1CF9000F007C117D /* Main.storyboard */,
- 97C146FD1CF9000F007C117D /* Assets.xcassets */,
- 97C146FF1CF9000F007C117D /* LaunchScreen.storyboard */,
- 97C147021CF9000F007C117D /* Info.plist */,
- 1498D2321E8E86230040F4C2 /* GeneratedPluginRegistrant.h */,
- 1498D2331E8E89220040F4C2 /* GeneratedPluginRegistrant.m */,
- 74858FAE1ED2DC5600515810 /* AppDelegate.swift */,
- 74858FAD1ED2DC5600515810 /* Runner-Bridging-Header.h */,
- );
- path = Runner;
- sourceTree = "";
- };
-/* End PBXGroup section */
-
-/* Begin PBXNativeTarget section */
- 97C146ED1CF9000F007C117D /* Runner */ = {
- isa = PBXNativeTarget;
- buildConfigurationList = 97C147051CF9000F007C117D /* Build configuration list for PBXNativeTarget "Runner" */;
- buildPhases = (
- 9740EEB61CF901F6004384FC /* Run Script */,
- 97C146EA1CF9000F007C117D /* Sources */,
- 97C146EB1CF9000F007C117D /* Frameworks */,
- 97C146EC1CF9000F007C117D /* Resources */,
- 9705A1C41CF9048500538489 /* Embed Frameworks */,
- 3B06AD1E1E4923F5004D2608 /* Thin Binary */,
- );
- buildRules = (
- );
- dependencies = (
- );
- name = Runner;
- productName = Runner;
- productReference = 97C146EE1CF9000F007C117D /* Runner.app */;
- productType = "com.apple.product-type.application";
- };
-/* End PBXNativeTarget section */
-
-/* Begin PBXProject section */
- 97C146E61CF9000F007C117D /* Project object */ = {
- isa = PBXProject;
- attributes = {
- LastUpgradeCheck = 1300;
- ORGANIZATIONNAME = "";
- TargetAttributes = {
- 97C146ED1CF9000F007C117D = {
- CreatedOnToolsVersion = 7.3.1;
- LastSwiftMigration = 1100;
- };
- };
- };
- buildConfigurationList = 97C146E91CF9000F007C117D /* Build configuration list for PBXProject "Runner" */;
- compatibilityVersion = "Xcode 9.3";
- developmentRegion = en;
- hasScannedForEncodings = 0;
- knownRegions = (
- en,
- Base,
- );
- mainGroup = 97C146E51CF9000F007C117D;
- productRefGroup = 97C146EF1CF9000F007C117D /* Products */;
- projectDirPath = "";
- projectRoot = "";
- targets = (
- 97C146ED1CF9000F007C117D /* Runner */,
- );
- };
-/* End PBXProject section */
-
-/* Begin PBXResourcesBuildPhase section */
- 97C146EC1CF9000F007C117D /* Resources */ = {
- isa = PBXResourcesBuildPhase;
- buildActionMask = 2147483647;
- files = (
- 97C147011CF9000F007C117D /* LaunchScreen.storyboard in Resources */,
- 3B3967161E833CAA004F5970 /* AppFrameworkInfo.plist in Resources */,
- 97C146FE1CF9000F007C117D /* Assets.xcassets in Resources */,
- 97C146FC1CF9000F007C117D /* Main.storyboard in Resources */,
- );
- runOnlyForDeploymentPostprocessing = 0;
- };
-/* End PBXResourcesBuildPhase section */
-
-/* Begin PBXShellScriptBuildPhase section */
- 3B06AD1E1E4923F5004D2608 /* Thin Binary */ = {
- isa = PBXShellScriptBuildPhase;
- buildActionMask = 2147483647;
- files = (
- );
- inputPaths = (
- );
- name = "Thin Binary";
- outputPaths = (
- );
- runOnlyForDeploymentPostprocessing = 0;
- shellPath = /bin/sh;
- shellScript = "/bin/sh \"$FLUTTER_ROOT/packages/flutter_tools/bin/xcode_backend.sh\" embed_and_thin";
- };
- 9740EEB61CF901F6004384FC /* Run Script */ = {
- isa = PBXShellScriptBuildPhase;
- buildActionMask = 2147483647;
- files = (
- );
- inputPaths = (
- );
- name = "Run Script";
- outputPaths = (
- );
- runOnlyForDeploymentPostprocessing = 0;
- shellPath = /bin/sh;
- shellScript = "/bin/sh \"$FLUTTER_ROOT/packages/flutter_tools/bin/xcode_backend.sh\" build";
- };
-/* End PBXShellScriptBuildPhase section */
-
-/* Begin PBXSourcesBuildPhase section */
- 97C146EA1CF9000F007C117D /* Sources */ = {
- isa = PBXSourcesBuildPhase;
- buildActionMask = 2147483647;
- files = (
- 74858FAF1ED2DC5600515810 /* AppDelegate.swift in Sources */,
- 1498D2341E8E89220040F4C2 /* GeneratedPluginRegistrant.m in Sources */,
- );
- runOnlyForDeploymentPostprocessing = 0;
- };
-/* End PBXSourcesBuildPhase section */
-
-/* Begin PBXVariantGroup section */
- 97C146FA1CF9000F007C117D /* Main.storyboard */ = {
- isa = PBXVariantGroup;
- children = (
- 97C146FB1CF9000F007C117D /* Base */,
- );
- name = Main.storyboard;
- sourceTree = "";
- };
- 97C146FF1CF9000F007C117D /* LaunchScreen.storyboard */ = {
- isa = PBXVariantGroup;
- children = (
- 97C147001CF9000F007C117D /* Base */,
- );
- name = LaunchScreen.storyboard;
- sourceTree = "";
- };
-/* End PBXVariantGroup section */
-
-/* Begin XCBuildConfiguration section */
- 249021D3217E4FDB00AE95B9 /* Profile */ = {
- isa = XCBuildConfiguration;
- buildSettings = {
- ALWAYS_SEARCH_USER_PATHS = NO;
- CLANG_ANALYZER_NONNULL = YES;
- CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
- CLANG_CXX_LIBRARY = "libc++";
- CLANG_ENABLE_MODULES = YES;
- CLANG_ENABLE_OBJC_ARC = YES;
- CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
- CLANG_WARN_BOOL_CONVERSION = YES;
- CLANG_WARN_COMMA = YES;
- CLANG_WARN_CONSTANT_CONVERSION = YES;
- CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES;
- CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
- CLANG_WARN_EMPTY_BODY = YES;
- CLANG_WARN_ENUM_CONVERSION = YES;
- CLANG_WARN_INFINITE_RECURSION = YES;
- CLANG_WARN_INT_CONVERSION = YES;
- CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;
- CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES;
- CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
- CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
- CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
- CLANG_WARN_STRICT_PROTOTYPES = YES;
- CLANG_WARN_SUSPICIOUS_MOVE = YES;
- CLANG_WARN_UNREACHABLE_CODE = YES;
- CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
- "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
- COPY_PHASE_STRIP = NO;
- DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
- ENABLE_NS_ASSERTIONS = NO;
- ENABLE_STRICT_OBJC_MSGSEND = YES;
- GCC_C_LANGUAGE_STANDARD = gnu99;
- GCC_NO_COMMON_BLOCKS = YES;
- GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
- GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
- GCC_WARN_UNDECLARED_SELECTOR = YES;
- GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
- GCC_WARN_UNUSED_FUNCTION = YES;
- GCC_WARN_UNUSED_VARIABLE = YES;
- IPHONEOS_DEPLOYMENT_TARGET = 9.0;
- MTL_ENABLE_DEBUG_INFO = NO;
- SDKROOT = iphoneos;
- SUPPORTED_PLATFORMS = iphoneos;
- TARGETED_DEVICE_FAMILY = "1,2";
- VALIDATE_PRODUCT = YES;
- };
- name = Profile;
- };
- 249021D4217E4FDB00AE95B9 /* Profile */ = {
- isa = XCBuildConfiguration;
- baseConfigurationReference = 7AFA3C8E1D35360C0083082E /* Release.xcconfig */;
- buildSettings = {
- ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
- CLANG_ENABLE_MODULES = YES;
- CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)";
- DEVELOPMENT_TEAM = 6Z5P8GG96U;
- ENABLE_BITCODE = NO;
- INFOPLIST_FILE = Runner/Info.plist;
- LD_RUNPATH_SEARCH_PATHS = (
- "$(inherited)",
- "@executable_path/Frameworks",
- );
- PRODUCT_BUNDLE_IDENTIFIER = fr.pointcheval.nativeCryptoExample;
- PRODUCT_NAME = "$(TARGET_NAME)";
- SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h";
- SWIFT_VERSION = 5.0;
- VERSIONING_SYSTEM = "apple-generic";
- };
- name = Profile;
- };
- 97C147031CF9000F007C117D /* Debug */ = {
- isa = XCBuildConfiguration;
- buildSettings = {
- ALWAYS_SEARCH_USER_PATHS = NO;
- CLANG_ANALYZER_NONNULL = YES;
- CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
- CLANG_CXX_LIBRARY = "libc++";
- CLANG_ENABLE_MODULES = YES;
- CLANG_ENABLE_OBJC_ARC = YES;
- CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
- CLANG_WARN_BOOL_CONVERSION = YES;
- CLANG_WARN_COMMA = YES;
- CLANG_WARN_CONSTANT_CONVERSION = YES;
- CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES;
- CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
- CLANG_WARN_EMPTY_BODY = YES;
- CLANG_WARN_ENUM_CONVERSION = YES;
- CLANG_WARN_INFINITE_RECURSION = YES;
- CLANG_WARN_INT_CONVERSION = YES;
- CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;
- CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES;
- CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
- CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
- CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
- CLANG_WARN_STRICT_PROTOTYPES = YES;
- CLANG_WARN_SUSPICIOUS_MOVE = YES;
- CLANG_WARN_UNREACHABLE_CODE = YES;
- CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
- "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
- COPY_PHASE_STRIP = NO;
- DEBUG_INFORMATION_FORMAT = dwarf;
- ENABLE_STRICT_OBJC_MSGSEND = YES;
- ENABLE_TESTABILITY = YES;
- GCC_C_LANGUAGE_STANDARD = gnu99;
- GCC_DYNAMIC_NO_PIC = NO;
- GCC_NO_COMMON_BLOCKS = YES;
- GCC_OPTIMIZATION_LEVEL = 0;
- GCC_PREPROCESSOR_DEFINITIONS = (
- "DEBUG=1",
- "$(inherited)",
- );
- GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
- GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
- GCC_WARN_UNDECLARED_SELECTOR = YES;
- GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
- GCC_WARN_UNUSED_FUNCTION = YES;
- GCC_WARN_UNUSED_VARIABLE = YES;
- IPHONEOS_DEPLOYMENT_TARGET = 9.0;
- MTL_ENABLE_DEBUG_INFO = YES;
- ONLY_ACTIVE_ARCH = YES;
- SDKROOT = iphoneos;
- TARGETED_DEVICE_FAMILY = "1,2";
- };
- name = Debug;
- };
- 97C147041CF9000F007C117D /* Release */ = {
- isa = XCBuildConfiguration;
- buildSettings = {
- ALWAYS_SEARCH_USER_PATHS = NO;
- CLANG_ANALYZER_NONNULL = YES;
- CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
- CLANG_CXX_LIBRARY = "libc++";
- CLANG_ENABLE_MODULES = YES;
- CLANG_ENABLE_OBJC_ARC = YES;
- CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
- CLANG_WARN_BOOL_CONVERSION = YES;
- CLANG_WARN_COMMA = YES;
- CLANG_WARN_CONSTANT_CONVERSION = YES;
- CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES;
- CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
- CLANG_WARN_EMPTY_BODY = YES;
- CLANG_WARN_ENUM_CONVERSION = YES;
- CLANG_WARN_INFINITE_RECURSION = YES;
- CLANG_WARN_INT_CONVERSION = YES;
- CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;
- CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES;
- CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
- CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
- CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
- CLANG_WARN_STRICT_PROTOTYPES = YES;
- CLANG_WARN_SUSPICIOUS_MOVE = YES;
- CLANG_WARN_UNREACHABLE_CODE = YES;
- CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
- "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
- COPY_PHASE_STRIP = NO;
- DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
- ENABLE_NS_ASSERTIONS = NO;
- ENABLE_STRICT_OBJC_MSGSEND = YES;
- GCC_C_LANGUAGE_STANDARD = gnu99;
- GCC_NO_COMMON_BLOCKS = YES;
- GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
- GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
- GCC_WARN_UNDECLARED_SELECTOR = YES;
- GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
- GCC_WARN_UNUSED_FUNCTION = YES;
- GCC_WARN_UNUSED_VARIABLE = YES;
- IPHONEOS_DEPLOYMENT_TARGET = 9.0;
- MTL_ENABLE_DEBUG_INFO = NO;
- SDKROOT = iphoneos;
- SUPPORTED_PLATFORMS = iphoneos;
- SWIFT_COMPILATION_MODE = wholemodule;
- SWIFT_OPTIMIZATION_LEVEL = "-O";
- TARGETED_DEVICE_FAMILY = "1,2";
- VALIDATE_PRODUCT = YES;
- };
- name = Release;
- };
- 97C147061CF9000F007C117D /* Debug */ = {
- isa = XCBuildConfiguration;
- baseConfigurationReference = 9740EEB21CF90195004384FC /* Debug.xcconfig */;
- buildSettings = {
- ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
- CLANG_ENABLE_MODULES = YES;
- CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)";
- DEVELOPMENT_TEAM = 6Z5P8GG96U;
- ENABLE_BITCODE = NO;
- INFOPLIST_FILE = Runner/Info.plist;
- LD_RUNPATH_SEARCH_PATHS = (
- "$(inherited)",
- "@executable_path/Frameworks",
- );
- PRODUCT_BUNDLE_IDENTIFIER = fr.pointcheval.nativeCryptoExample;
- PRODUCT_NAME = "$(TARGET_NAME)";
- SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h";
- SWIFT_OPTIMIZATION_LEVEL = "-Onone";
- SWIFT_VERSION = 5.0;
- VERSIONING_SYSTEM = "apple-generic";
- };
- name = Debug;
- };
- 97C147071CF9000F007C117D /* Release */ = {
- isa = XCBuildConfiguration;
- baseConfigurationReference = 7AFA3C8E1D35360C0083082E /* Release.xcconfig */;
- buildSettings = {
- ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
- CLANG_ENABLE_MODULES = YES;
- CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)";
- DEVELOPMENT_TEAM = 6Z5P8GG96U;
- ENABLE_BITCODE = NO;
- INFOPLIST_FILE = Runner/Info.plist;
- LD_RUNPATH_SEARCH_PATHS = (
- "$(inherited)",
- "@executable_path/Frameworks",
- );
- PRODUCT_BUNDLE_IDENTIFIER = fr.pointcheval.nativeCryptoExample;
- PRODUCT_NAME = "$(TARGET_NAME)";
- SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h";
- SWIFT_VERSION = 5.0;
- VERSIONING_SYSTEM = "apple-generic";
- };
- name = Release;
- };
-/* End XCBuildConfiguration section */
-
-/* Begin XCConfigurationList section */
- 97C146E91CF9000F007C117D /* Build configuration list for PBXProject "Runner" */ = {
- isa = XCConfigurationList;
- buildConfigurations = (
- 97C147031CF9000F007C117D /* Debug */,
- 97C147041CF9000F007C117D /* Release */,
- 249021D3217E4FDB00AE95B9 /* Profile */,
- );
- defaultConfigurationIsVisible = 0;
- defaultConfigurationName = Release;
- };
- 97C147051CF9000F007C117D /* Build configuration list for PBXNativeTarget "Runner" */ = {
- isa = XCConfigurationList;
- buildConfigurations = (
- 97C147061CF9000F007C117D /* Debug */,
- 97C147071CF9000F007C117D /* Release */,
- 249021D4217E4FDB00AE95B9 /* Profile */,
- );
- defaultConfigurationIsVisible = 0;
- defaultConfigurationName = Release;
- };
-/* End XCConfigurationList section */
- };
- rootObject = 97C146E61CF9000F007C117D /* Project object */;
-}
diff --git a/native_crypto/example/ios/Runner.xcworkspace/contents.xcworkspacedata b/native_crypto/example/ios/Runner.xcworkspace/contents.xcworkspacedata
deleted file mode 100644
index 1d526a1..0000000
--- a/native_crypto/example/ios/Runner.xcworkspace/contents.xcworkspacedata
+++ /dev/null
@@ -1,7 +0,0 @@
-
-
-
-
-
diff --git a/native_crypto/example/lib/main.dart b/native_crypto/example/lib/main.dart
deleted file mode 100644
index 322f70f..0000000
--- a/native_crypto/example/lib/main.dart
+++ /dev/null
@@ -1,62 +0,0 @@
-import 'package:flutter/material.dart';
-import 'dart:async';
-
-import 'package:flutter/services.dart';
-import 'package:native_crypto/native_crypto.dart';
-
-void main() {
- runApp(const MyApp());
-}
-
-class MyApp extends StatefulWidget {
- const MyApp({Key? key}) : super(key: key);
-
- @override
- State createState() => _MyAppState();
-}
-
-class _MyAppState extends State {
- String _platformVersion = 'Unknown';
-
- @override
- void initState() {
- super.initState();
- initPlatformState();
- }
-
- // Platform messages are asynchronous, so we initialize in an async method.
- Future initPlatformState() async {
- String platformVersion;
- // Platform messages may fail, so we use a try/catch PlatformException.
- // We also handle the message potentially returning null.
- try {
- platformVersion =
- await NativeCrypto.platformVersion ?? 'Unknown platform version';
- } on PlatformException {
- platformVersion = 'Failed to get platform version.';
- }
-
- // If the widget was removed from the tree while the asynchronous platform
- // message was in flight, we want to discard the reply rather than calling
- // setState to update our non-existent appearance.
- if (!mounted) return;
-
- setState(() {
- _platformVersion = platformVersion;
- });
- }
-
- @override
- Widget build(BuildContext context) {
- return MaterialApp(
- home: Scaffold(
- appBar: AppBar(
- title: const Text('Plugin example app'),
- ),
- body: Center(
- child: Text('Running on: $_platformVersion\n'),
- ),
- ),
- );
- }
-}
diff --git a/native_crypto/example/test/widget_test.dart b/native_crypto/example/test/widget_test.dart
deleted file mode 100644
index ffdf51c..0000000
--- a/native_crypto/example/test/widget_test.dart
+++ /dev/null
@@ -1,27 +0,0 @@
-// This is a basic Flutter widget test.
-//
-// To perform an interaction with a widget in your test, use the WidgetTester
-// utility that Flutter provides. For example, you can send tap and scroll
-// gestures. You can also use WidgetTester to find child widgets in the widget
-// tree, read text, and verify that the values of widget properties are correct.
-
-import 'package:flutter/material.dart';
-import 'package:flutter_test/flutter_test.dart';
-
-import 'package:native_crypto_example/main.dart';
-
-void main() {
- testWidgets('Verify Platform version', (WidgetTester tester) async {
- // Build our app and trigger a frame.
- await tester.pumpWidget(const MyApp());
-
- // Verify that platform version is retrieved.
- expect(
- find.byWidgetPredicate(
- (Widget widget) => widget is Text &&
- widget.data!.startsWith('Running on:'),
- ),
- findsOneWidget,
- );
- });
-}
diff --git a/native_crypto/lib/native_crypto.dart b/native_crypto/lib/native_crypto.dart
deleted file mode 100644
index 1036e3a..0000000
--- a/native_crypto/lib/native_crypto.dart
+++ /dev/null
@@ -1,17 +0,0 @@
-// You have generated a new plugin project without
-// specifying the `--platforms` flag. A plugin project supports no platforms is generated.
-// To add platforms, run `flutter create -t plugin --platforms .` under the same
-// directory. You can also find a detailed instruction on how to add platforms in the `pubspec.yaml` at https://flutter.dev/docs/development/packages-and-plugins/developing-packages#plugin-platforms.
-
-import 'dart:async';
-
-import 'package:flutter/services.dart';
-
-class NativeCrypto {
- static const MethodChannel _channel = MethodChannel('native_crypto');
-
- static Future get platformVersion async {
- final String? version = await _channel.invokeMethod('getPlatformVersion');
- return version;
- }
-}
diff --git a/native_crypto/pubspec.yaml b/native_crypto/pubspec.yaml
deleted file mode 100644
index 3baf2be..0000000
--- a/native_crypto/pubspec.yaml
+++ /dev/null
@@ -1,28 +0,0 @@
-name: native_crypto
-description: Fast and secure cryptography for Flutter.
-version: 0.0.7
-publish_to: 'none'
-
-environment:
- sdk: ">=2.15.0 <3.0.0"
- flutter: ">=2.5.0"
-
-dependencies:
- flutter:
- sdk: flutter
-
- native_crypto_ios:
- path: ../native_crypto_ios
-
-dev_dependencies:
- flutter_test:
- sdk: flutter
- flutter_lints: ^1.0.4
-
-flutter:
- plugin:
- platforms:
- # android:
- # default_package: native_crypto_android
- ios:
- default_package: native_crypto_ios
\ No newline at end of file
diff --git a/native_crypto/test/native_crypto_test.dart b/native_crypto/test/native_crypto_test.dart
deleted file mode 100644
index 5caceab..0000000
--- a/native_crypto/test/native_crypto_test.dart
+++ /dev/null
@@ -1,23 +0,0 @@
-import 'package:flutter/services.dart';
-import 'package:flutter_test/flutter_test.dart';
-import 'package:native_crypto/native_crypto.dart';
-
-void main() {
- const MethodChannel channel = MethodChannel('native_crypto');
-
- TestWidgetsFlutterBinding.ensureInitialized();
-
- setUp(() {
- channel.setMockMethodCallHandler((MethodCall methodCall) async {
- return '42';
- });
- });
-
- tearDown(() {
- channel.setMockMethodCallHandler(null);
- });
-
- test('getPlatformVersion', () async {
- expect(await NativeCrypto.platformVersion, '42');
- });
-}
diff --git a/native_crypto_ios/CHANGELOG.md b/native_crypto_ios/CHANGELOG.md
deleted file mode 100644
index 41cc7d8..0000000
--- a/native_crypto_ios/CHANGELOG.md
+++ /dev/null
@@ -1,3 +0,0 @@
-## 0.0.1
-
-* TODO: Describe initial release.
diff --git a/native_crypto_ios/example/README.md b/native_crypto_ios/example/README.md
deleted file mode 100644
index 340d8c1..0000000
--- a/native_crypto_ios/example/README.md
+++ /dev/null
@@ -1,16 +0,0 @@
-# native_crypto_ios_example
-
-Demonstrates how to use the native_crypto_ios plugin.
-
-## Getting Started
-
-This project is a starting point for a Flutter application.
-
-A few resources to get you started if this is your first Flutter project:
-
-- [Lab: Write your first Flutter app](https://flutter.dev/docs/get-started/codelab)
-- [Cookbook: Useful Flutter samples](https://flutter.dev/docs/cookbook)
-
-For help getting started with Flutter, view our
-[online documentation](https://flutter.dev/docs), which offers tutorials,
-samples, guidance on mobile development, and a full API reference.
diff --git a/native_crypto_ios/example/analysis_options.yaml b/native_crypto_ios/example/analysis_options.yaml
deleted file mode 100644
index 61b6c4d..0000000
--- a/native_crypto_ios/example/analysis_options.yaml
+++ /dev/null
@@ -1,29 +0,0 @@
-# This file configures the analyzer, which statically analyzes Dart code to
-# check for errors, warnings, and lints.
-#
-# The issues identified by the analyzer are surfaced in the UI of Dart-enabled
-# IDEs (https://dart.dev/tools#ides-and-editors). The analyzer can also be
-# invoked from the command line by running `flutter analyze`.
-
-# The following line activates a set of recommended lints for Flutter apps,
-# packages, and plugins designed to encourage good coding practices.
-include: package:flutter_lints/flutter.yaml
-
-linter:
- # The lint rules applied to this project can be customized in the
- # section below to disable rules from the `package:flutter_lints/flutter.yaml`
- # included above or to enable additional rules. A list of all available lints
- # and their documentation is published at
- # https://dart-lang.github.io/linter/lints/index.html.
- #
- # Instead of disabling a lint rule for the entire project in the
- # section below, it can also be suppressed for a single line of code
- # or a specific dart file by using the `// ignore: name_of_lint` and
- # `// ignore_for_file: name_of_lint` syntax on the line or in the file
- # producing the lint.
- rules:
- # avoid_print: false # Uncomment to disable the `avoid_print` rule
- # prefer_single_quotes: true # Uncomment to enable the `prefer_single_quotes` rule
-
-# Additional information about this file can be found at
-# https://dart.dev/guides/language/analysis-options
diff --git a/native_crypto_ios/example/ios/.gitignore b/native_crypto_ios/example/ios/.gitignore
deleted file mode 100644
index 7a7f987..0000000
--- a/native_crypto_ios/example/ios/.gitignore
+++ /dev/null
@@ -1,34 +0,0 @@
-**/dgph
-*.mode1v3
-*.mode2v3
-*.moved-aside
-*.pbxuser
-*.perspectivev3
-**/*sync/
-.sconsign.dblite
-.tags*
-**/.vagrant/
-**/DerivedData/
-Icon?
-**/Pods/
-**/.symlinks/
-profile
-xcuserdata
-**/.generated/
-Flutter/App.framework
-Flutter/Flutter.framework
-Flutter/Flutter.podspec
-Flutter/Generated.xcconfig
-Flutter/ephemeral/
-Flutter/app.flx
-Flutter/app.zip
-Flutter/flutter_assets/
-Flutter/flutter_export_environment.sh
-ServiceDefinitions.json
-Runner/GeneratedPluginRegistrant.*
-
-# Exceptions to above rules.
-!default.mode1v3
-!default.mode2v3
-!default.pbxuser
-!default.perspectivev3
diff --git a/native_crypto_ios/example/ios/Flutter/AppFrameworkInfo.plist b/native_crypto_ios/example/ios/Flutter/AppFrameworkInfo.plist
deleted file mode 100644
index 8d4492f..0000000
--- a/native_crypto_ios/example/ios/Flutter/AppFrameworkInfo.plist
+++ /dev/null
@@ -1,26 +0,0 @@
-
-
-
-
- CFBundleDevelopmentRegion
- en
- CFBundleExecutable
- App
- CFBundleIdentifier
- io.flutter.flutter.app
- CFBundleInfoDictionaryVersion
- 6.0
- CFBundleName
- App
- CFBundlePackageType
- FMWK
- CFBundleShortVersionString
- 1.0
- CFBundleSignature
- ????
- CFBundleVersion
- 1.0
- MinimumOSVersion
- 9.0
-
-
diff --git a/native_crypto_ios/example/ios/Flutter/Debug.xcconfig b/native_crypto_ios/example/ios/Flutter/Debug.xcconfig
deleted file mode 100644
index ec97fc6..0000000
--- a/native_crypto_ios/example/ios/Flutter/Debug.xcconfig
+++ /dev/null
@@ -1,2 +0,0 @@
-#include? "Pods/Target Support Files/Pods-Runner/Pods-Runner.debug.xcconfig"
-#include "Generated.xcconfig"
diff --git a/native_crypto_ios/example/ios/Flutter/Release.xcconfig b/native_crypto_ios/example/ios/Flutter/Release.xcconfig
deleted file mode 100644
index c4855bf..0000000
--- a/native_crypto_ios/example/ios/Flutter/Release.xcconfig
+++ /dev/null
@@ -1,2 +0,0 @@
-#include? "Pods/Target Support Files/Pods-Runner/Pods-Runner.release.xcconfig"
-#include "Generated.xcconfig"
diff --git a/native_crypto_ios/example/ios/Podfile b/native_crypto_ios/example/ios/Podfile
deleted file mode 100644
index 1e8c3c9..0000000
--- a/native_crypto_ios/example/ios/Podfile
+++ /dev/null
@@ -1,41 +0,0 @@
-# Uncomment this line to define a global platform for your project
-# platform :ios, '9.0'
-
-# CocoaPods analytics sends network stats synchronously affecting flutter build latency.
-ENV['COCOAPODS_DISABLE_STATS'] = 'true'
-
-project 'Runner', {
- 'Debug' => :debug,
- 'Profile' => :release,
- 'Release' => :release,
-}
-
-def flutter_root
- generated_xcode_build_settings_path = File.expand_path(File.join('..', 'Flutter', 'Generated.xcconfig'), __FILE__)
- unless File.exist?(generated_xcode_build_settings_path)
- raise "#{generated_xcode_build_settings_path} must exist. If you're running pod install manually, make sure flutter pub get is executed first"
- end
-
- File.foreach(generated_xcode_build_settings_path) do |line|
- matches = line.match(/FLUTTER_ROOT\=(.*)/)
- return matches[1].strip if matches
- end
- raise "FLUTTER_ROOT not found in #{generated_xcode_build_settings_path}. Try deleting Generated.xcconfig, then run flutter pub get"
-end
-
-require File.expand_path(File.join('packages', 'flutter_tools', 'bin', 'podhelper'), flutter_root)
-
-flutter_ios_podfile_setup
-
-target 'Runner' do
- use_frameworks!
- use_modular_headers!
-
- flutter_install_all_ios_pods File.dirname(File.realpath(__FILE__))
-end
-
-post_install do |installer|
- installer.pods_project.targets.each do |target|
- flutter_additional_ios_build_settings(target)
- end
-end
diff --git a/native_crypto_ios/example/ios/Runner.xcodeproj/project.xcworkspace/contents.xcworkspacedata b/native_crypto_ios/example/ios/Runner.xcodeproj/project.xcworkspace/contents.xcworkspacedata
deleted file mode 100644
index 919434a..0000000
--- a/native_crypto_ios/example/ios/Runner.xcodeproj/project.xcworkspace/contents.xcworkspacedata
+++ /dev/null
@@ -1,7 +0,0 @@
-
-
-
-
-
diff --git a/native_crypto_ios/example/ios/Runner.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist b/native_crypto_ios/example/ios/Runner.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist
deleted file mode 100644
index 18d9810..0000000
--- a/native_crypto_ios/example/ios/Runner.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist
+++ /dev/null
@@ -1,8 +0,0 @@
-
-
-
-
- IDEDidComputeMac32BitWarning
-
-
-
diff --git a/native_crypto_ios/example/ios/Runner.xcodeproj/project.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings b/native_crypto_ios/example/ios/Runner.xcodeproj/project.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings
deleted file mode 100644
index f9b0d7c..0000000
--- a/native_crypto_ios/example/ios/Runner.xcodeproj/project.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings
+++ /dev/null
@@ -1,8 +0,0 @@
-
-
-
-
- PreviewsEnabled
-
-
-
diff --git a/native_crypto_ios/example/ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme b/native_crypto_ios/example/ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme
deleted file mode 100644
index c87d15a..0000000
--- a/native_crypto_ios/example/ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme
+++ /dev/null
@@ -1,87 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/native_crypto_ios/example/ios/Runner.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist b/native_crypto_ios/example/ios/Runner.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist
deleted file mode 100644
index 18d9810..0000000
--- a/native_crypto_ios/example/ios/Runner.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist
+++ /dev/null
@@ -1,8 +0,0 @@
-
-
-
-
- IDEDidComputeMac32BitWarning
-
-
-
diff --git a/native_crypto_ios/example/ios/Runner.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings b/native_crypto_ios/example/ios/Runner.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings
deleted file mode 100644
index f9b0d7c..0000000
--- a/native_crypto_ios/example/ios/Runner.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings
+++ /dev/null
@@ -1,8 +0,0 @@
-
-
-
-
- PreviewsEnabled
-
-
-
diff --git a/native_crypto_ios/example/ios/Runner/AppDelegate.swift b/native_crypto_ios/example/ios/Runner/AppDelegate.swift
deleted file mode 100644
index 70693e4..0000000
--- a/native_crypto_ios/example/ios/Runner/AppDelegate.swift
+++ /dev/null
@@ -1,13 +0,0 @@
-import UIKit
-import Flutter
-
-@UIApplicationMain
-@objc class AppDelegate: FlutterAppDelegate {
- override func application(
- _ application: UIApplication,
- didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?
- ) -> Bool {
- GeneratedPluginRegistrant.register(with: self)
- return super.application(application, didFinishLaunchingWithOptions: launchOptions)
- }
-}
diff --git a/native_crypto_ios/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Contents.json b/native_crypto_ios/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Contents.json
deleted file mode 100644
index d36b1fa..0000000
--- a/native_crypto_ios/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Contents.json
+++ /dev/null
@@ -1,122 +0,0 @@
-{
- "images" : [
- {
- "size" : "20x20",
- "idiom" : "iphone",
- "filename" : "Icon-App-20x20@2x.png",
- "scale" : "2x"
- },
- {
- "size" : "20x20",
- "idiom" : "iphone",
- "filename" : "Icon-App-20x20@3x.png",
- "scale" : "3x"
- },
- {
- "size" : "29x29",
- "idiom" : "iphone",
- "filename" : "Icon-App-29x29@1x.png",
- "scale" : "1x"
- },
- {
- "size" : "29x29",
- "idiom" : "iphone",
- "filename" : "Icon-App-29x29@2x.png",
- "scale" : "2x"
- },
- {
- "size" : "29x29",
- "idiom" : "iphone",
- "filename" : "Icon-App-29x29@3x.png",
- "scale" : "3x"
- },
- {
- "size" : "40x40",
- "idiom" : "iphone",
- "filename" : "Icon-App-40x40@2x.png",
- "scale" : "2x"
- },
- {
- "size" : "40x40",
- "idiom" : "iphone",
- "filename" : "Icon-App-40x40@3x.png",
- "scale" : "3x"
- },
- {
- "size" : "60x60",
- "idiom" : "iphone",
- "filename" : "Icon-App-60x60@2x.png",
- "scale" : "2x"
- },
- {
- "size" : "60x60",
- "idiom" : "iphone",
- "filename" : "Icon-App-60x60@3x.png",
- "scale" : "3x"
- },
- {
- "size" : "20x20",
- "idiom" : "ipad",
- "filename" : "Icon-App-20x20@1x.png",
- "scale" : "1x"
- },
- {
- "size" : "20x20",
- "idiom" : "ipad",
- "filename" : "Icon-App-20x20@2x.png",
- "scale" : "2x"
- },
- {
- "size" : "29x29",
- "idiom" : "ipad",
- "filename" : "Icon-App-29x29@1x.png",
- "scale" : "1x"
- },
- {
- "size" : "29x29",
- "idiom" : "ipad",
- "filename" : "Icon-App-29x29@2x.png",
- "scale" : "2x"
- },
- {
- "size" : "40x40",
- "idiom" : "ipad",
- "filename" : "Icon-App-40x40@1x.png",
- "scale" : "1x"
- },
- {
- "size" : "40x40",
- "idiom" : "ipad",
- "filename" : "Icon-App-40x40@2x.png",
- "scale" : "2x"
- },
- {
- "size" : "76x76",
- "idiom" : "ipad",
- "filename" : "Icon-App-76x76@1x.png",
- "scale" : "1x"
- },
- {
- "size" : "76x76",
- "idiom" : "ipad",
- "filename" : "Icon-App-76x76@2x.png",
- "scale" : "2x"
- },
- {
- "size" : "83.5x83.5",
- "idiom" : "ipad",
- "filename" : "Icon-App-83.5x83.5@2x.png",
- "scale" : "2x"
- },
- {
- "size" : "1024x1024",
- "idiom" : "ios-marketing",
- "filename" : "Icon-App-1024x1024@1x.png",
- "scale" : "1x"
- }
- ],
- "info" : {
- "version" : 1,
- "author" : "xcode"
- }
-}
diff --git a/native_crypto_ios/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-1024x1024@1x.png b/native_crypto_ios/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-1024x1024@1x.png
deleted file mode 100644
index dc9ada4..0000000
Binary files a/native_crypto_ios/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-1024x1024@1x.png and /dev/null differ
diff --git a/native_crypto_ios/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@1x.png b/native_crypto_ios/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@1x.png
deleted file mode 100644
index 28c6bf0..0000000
Binary files a/native_crypto_ios/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@1x.png and /dev/null differ
diff --git a/native_crypto_ios/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@2x.png b/native_crypto_ios/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@2x.png
deleted file mode 100644
index 2ccbfd9..0000000
Binary files a/native_crypto_ios/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@2x.png and /dev/null differ
diff --git a/native_crypto_ios/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@3x.png b/native_crypto_ios/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@3x.png
deleted file mode 100644
index f091b6b..0000000
Binary files a/native_crypto_ios/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@3x.png and /dev/null differ
diff --git a/native_crypto_ios/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@1x.png b/native_crypto_ios/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@1x.png
deleted file mode 100644
index 4cde121..0000000
Binary files a/native_crypto_ios/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@1x.png and /dev/null differ
diff --git a/native_crypto_ios/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@2x.png b/native_crypto_ios/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@2x.png
deleted file mode 100644
index d0ef06e..0000000
Binary files a/native_crypto_ios/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@2x.png and /dev/null differ
diff --git a/native_crypto_ios/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@3x.png b/native_crypto_ios/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@3x.png
deleted file mode 100644
index dcdc230..0000000
Binary files a/native_crypto_ios/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@3x.png and /dev/null differ
diff --git a/native_crypto_ios/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@1x.png b/native_crypto_ios/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@1x.png
deleted file mode 100644
index 2ccbfd9..0000000
Binary files a/native_crypto_ios/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@1x.png and /dev/null differ
diff --git a/native_crypto_ios/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@2x.png b/native_crypto_ios/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@2x.png
deleted file mode 100644
index c8f9ed8..0000000
Binary files a/native_crypto_ios/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@2x.png and /dev/null differ
diff --git a/native_crypto_ios/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@3x.png b/native_crypto_ios/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@3x.png
deleted file mode 100644
index a6d6b86..0000000
Binary files a/native_crypto_ios/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@3x.png and /dev/null differ
diff --git a/native_crypto_ios/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@2x.png b/native_crypto_ios/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@2x.png
deleted file mode 100644
index a6d6b86..0000000
Binary files a/native_crypto_ios/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@2x.png and /dev/null differ
diff --git a/native_crypto_ios/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@3x.png b/native_crypto_ios/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@3x.png
deleted file mode 100644
index 75b2d16..0000000
Binary files a/native_crypto_ios/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@3x.png and /dev/null differ
diff --git a/native_crypto_ios/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@1x.png b/native_crypto_ios/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@1x.png
deleted file mode 100644
index c4df70d..0000000
Binary files a/native_crypto_ios/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@1x.png and /dev/null differ
diff --git a/native_crypto_ios/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@2x.png b/native_crypto_ios/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@2x.png
deleted file mode 100644
index 6a84f41..0000000
Binary files a/native_crypto_ios/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@2x.png and /dev/null differ
diff --git a/native_crypto_ios/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-83.5x83.5@2x.png b/native_crypto_ios/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-83.5x83.5@2x.png
deleted file mode 100644
index d0e1f58..0000000
Binary files a/native_crypto_ios/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-83.5x83.5@2x.png and /dev/null differ
diff --git a/native_crypto_ios/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/Contents.json b/native_crypto_ios/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/Contents.json
deleted file mode 100644
index 0bedcf2..0000000
--- a/native_crypto_ios/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/Contents.json
+++ /dev/null
@@ -1,23 +0,0 @@
-{
- "images" : [
- {
- "idiom" : "universal",
- "filename" : "LaunchImage.png",
- "scale" : "1x"
- },
- {
- "idiom" : "universal",
- "filename" : "LaunchImage@2x.png",
- "scale" : "2x"
- },
- {
- "idiom" : "universal",
- "filename" : "LaunchImage@3x.png",
- "scale" : "3x"
- }
- ],
- "info" : {
- "version" : 1,
- "author" : "xcode"
- }
-}
diff --git a/native_crypto_ios/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage.png b/native_crypto_ios/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage.png
deleted file mode 100644
index 9da19ea..0000000
Binary files a/native_crypto_ios/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage.png and /dev/null differ
diff --git a/native_crypto_ios/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@2x.png b/native_crypto_ios/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@2x.png
deleted file mode 100644
index 9da19ea..0000000
Binary files a/native_crypto_ios/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@2x.png and /dev/null differ
diff --git a/native_crypto_ios/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@3x.png b/native_crypto_ios/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@3x.png
deleted file mode 100644
index 9da19ea..0000000
Binary files a/native_crypto_ios/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@3x.png and /dev/null differ
diff --git a/native_crypto_ios/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/README.md b/native_crypto_ios/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/README.md
deleted file mode 100644
index 89c2725..0000000
--- a/native_crypto_ios/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/README.md
+++ /dev/null
@@ -1,5 +0,0 @@
-# Launch Screen Assets
-
-You can customize the launch screen with your own desired assets by replacing the image files in this directory.
-
-You can also do it by opening your Flutter project's Xcode project with `open ios/Runner.xcworkspace`, selecting `Runner/Assets.xcassets` in the Project Navigator and dropping in the desired images.
\ No newline at end of file
diff --git a/native_crypto_ios/example/ios/Runner/Base.lproj/LaunchScreen.storyboard b/native_crypto_ios/example/ios/Runner/Base.lproj/LaunchScreen.storyboard
deleted file mode 100644
index f2e259c..0000000
--- a/native_crypto_ios/example/ios/Runner/Base.lproj/LaunchScreen.storyboard
+++ /dev/null
@@ -1,37 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/native_crypto_ios/example/ios/Runner/Base.lproj/Main.storyboard b/native_crypto_ios/example/ios/Runner/Base.lproj/Main.storyboard
deleted file mode 100644
index f3c2851..0000000
--- a/native_crypto_ios/example/ios/Runner/Base.lproj/Main.storyboard
+++ /dev/null
@@ -1,26 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/native_crypto_ios/example/ios/Runner/Info.plist b/native_crypto_ios/example/ios/Runner/Info.plist
deleted file mode 100644
index 292a791..0000000
--- a/native_crypto_ios/example/ios/Runner/Info.plist
+++ /dev/null
@@ -1,47 +0,0 @@
-
-
-
-
- CFBundleDevelopmentRegion
- $(DEVELOPMENT_LANGUAGE)
- CFBundleDisplayName
- Native Crypto Ios
- CFBundleExecutable
- $(EXECUTABLE_NAME)
- CFBundleIdentifier
- $(PRODUCT_BUNDLE_IDENTIFIER)
- CFBundleInfoDictionaryVersion
- 6.0
- CFBundleName
- native_crypto_ios_example
- CFBundlePackageType
- APPL
- CFBundleShortVersionString
- $(FLUTTER_BUILD_NAME)
- CFBundleSignature
- ????
- CFBundleVersion
- $(FLUTTER_BUILD_NUMBER)
- LSRequiresIPhoneOS
-
- UILaunchStoryboardName
- LaunchScreen
- UIMainStoryboardFile
- Main
- UISupportedInterfaceOrientations
-
- UIInterfaceOrientationPortrait
- UIInterfaceOrientationLandscapeLeft
- UIInterfaceOrientationLandscapeRight
-
- UISupportedInterfaceOrientations~ipad
-
- UIInterfaceOrientationPortrait
- UIInterfaceOrientationPortraitUpsideDown
- UIInterfaceOrientationLandscapeLeft
- UIInterfaceOrientationLandscapeRight
-
- UIViewControllerBasedStatusBarAppearance
-
-
-
diff --git a/native_crypto_ios/example/ios/Runner/Runner-Bridging-Header.h b/native_crypto_ios/example/ios/Runner/Runner-Bridging-Header.h
deleted file mode 100644
index 308a2a5..0000000
--- a/native_crypto_ios/example/ios/Runner/Runner-Bridging-Header.h
+++ /dev/null
@@ -1 +0,0 @@
-#import "GeneratedPluginRegistrant.h"
diff --git a/native_crypto_ios/example/lib/main.dart b/native_crypto_ios/example/lib/main.dart
deleted file mode 100644
index 6636074..0000000
--- a/native_crypto_ios/example/lib/main.dart
+++ /dev/null
@@ -1,79 +0,0 @@
-import 'dart:typed_data';
-
-import 'package:flutter/material.dart';
-import 'dart:async';
-
-import 'package:flutter/services.dart';
-import 'package:native_crypto_platform_interface/native_crypto_platform_interface.dart';
-
-void main() {
- runApp(const MyApp());
-}
-
-class MyApp extends StatefulWidget {
- const MyApp({Key? key}) : super(key: key);
-
- @override
- State createState() => _MyAppState();
-}
-
-class _MyAppState extends State {
- String _platformVersion = 'Unknown';
-
- @override
- void initState() {
- super.initState();
- initPlatformState();
- }
-
- // Platform messages are asynchronous, so we initialize in an async method.
- Future initPlatformState() async {
- NativeCryptoPlatform _nativeCryptoPlatform = NativeCryptoPlatform.instance;
- String platformVersion;
- // Platform messages may fail, so we use a try/catch PlatformException.
- // We also handle the message potentially returning null.
- Uint8List? sk = await _nativeCryptoPlatform.generateSecretKey(256);
- print(sk ?? 'null');
-
- Uint8List? ciphertext = await _nativeCryptoPlatform.encrypt(Uint8List.fromList("abc".codeUnits), sk!, "aes");
- print(ciphertext ?? 'null');
-
- Uint8List? plaintext = await _nativeCryptoPlatform.decrypt(ciphertext!, sk, "aes");
- print(plaintext ?? 'null');
-
- Uint8List? kp = await _nativeCryptoPlatform.generateKeyPair();
- print(kp!.sublist(0, 31));
- print(kp.sublist(32).length);
-
- Uint8List? sharedSecret = await _nativeCryptoPlatform.generateSharedSecretKey(Uint8List.fromList("salt".codeUnits), 32, kp.sublist(0, 31), kp.sublist(32), "sha256");
-
- try {
- platformVersion = 'Unknown platform version';
- } on PlatformException {
- platformVersion = 'Failed to get platform version.';
- }
-
- // If the widget was removed from the tree while the asynchronous platform
- // message was in flight, we want to discard the reply rather than calling
- // setState to update our non-existent appearance.
- if (!mounted) return;
-
- setState(() {
- _platformVersion = platformVersion;
- });
- }
-
- @override
- Widget build(BuildContext context) {
- return MaterialApp(
- home: Scaffold(
- appBar: AppBar(
- title: const Text('Plugin example app'),
- ),
- body: Center(
- child: Text('Running on: $_platformVersion\n'),
- ),
- ),
- );
- }
-}
diff --git a/native_crypto_ios/example/pubspec.yaml b/native_crypto_ios/example/pubspec.yaml
deleted file mode 100644
index ab0098f..0000000
--- a/native_crypto_ios/example/pubspec.yaml
+++ /dev/null
@@ -1,87 +0,0 @@
-name: native_crypto_ios_example
-description: Demonstrates how to use the native_crypto_ios plugin.
-
-# The following line prevents the package from being accidentally published to
-# pub.dev using `flutter pub publish`. This is preferred for private packages.
-publish_to: 'none' # Remove this line if you wish to publish to pub.dev
-
-environment:
- sdk: ">=2.15.0 <3.0.0"
-
-# Dependencies specify other packages that your package needs in order to work.
-# To automatically upgrade your package dependencies to the latest versions
-# consider running `flutter pub upgrade --major-versions`. Alternatively,
-# dependencies can be manually updated by changing the version numbers below to
-# the latest version available on pub.dev. To see which dependencies have newer
-# versions available, run `flutter pub outdated`.
-dependencies:
- flutter:
- sdk: flutter
-
- native_crypto_ios:
- # When depending on this package from a real application you should use:
- # native_crypto_ios: ^x.y.z
- # See https://dart.dev/tools/pub/dependencies#version-constraints
- # The example app is bundled with the plugin so we use a path dependency on
- # the parent directory to use the current plugin's version.
- path: ../
-
- native_crypto_platform_interface:
- path: ../../native_crypto_platform_interface
-
- # The following adds the Cupertino Icons font to your application.
- # Use with the CupertinoIcons class for iOS style icons.
- cupertino_icons: ^1.0.2
-
-dev_dependencies:
- flutter_test:
- sdk: flutter
-
- # The "flutter_lints" package below contains a set of recommended lints to
- # encourage good coding practices. The lint set provided by the package is
- # activated in the `analysis_options.yaml` file located at the root of your
- # package. See that file for information about deactivating specific lint
- # rules and activating additional ones.
- flutter_lints: ^1.0.0
-
-# For information on the generic Dart part of this file, see the
-# following page: https://dart.dev/tools/pub/pubspec
-
-# The following section is specific to Flutter.
-flutter:
-
- # The following line ensures that the Material Icons font is
- # included with your application, so that you can use the icons in
- # the material Icons class.
- uses-material-design: true
-
- # To add assets to your application, add an assets section, like this:
- # assets:
- # - images/a_dot_burr.jpeg
- # - images/a_dot_ham.jpeg
-
- # An image asset can refer to one or more resolution-specific "variants", see
- # https://flutter.dev/assets-and-images/#resolution-aware.
-
- # For details regarding adding assets from package dependencies, see
- # https://flutter.dev/assets-and-images/#from-packages
-
- # To add custom fonts to your application, add a fonts section here,
- # in this "flutter" section. Each entry in this list should have a
- # "family" key with the font family name, and a "fonts" key with a
- # list giving the asset and other descriptors for the font. For
- # example:
- # fonts:
- # - family: Schyler
- # fonts:
- # - asset: fonts/Schyler-Regular.ttf
- # - asset: fonts/Schyler-Italic.ttf
- # style: italic
- # - family: Trajan Pro
- # fonts:
- # - asset: fonts/TrajanPro.ttf
- # - asset: fonts/TrajanPro_Bold.ttf
- # weight: 700
- #
- # For details regarding fonts from package dependencies,
- # see https://flutter.dev/custom-fonts/#from-packages
diff --git a/native_crypto_ios/example/test/widget_test.dart b/native_crypto_ios/example/test/widget_test.dart
deleted file mode 100644
index 75f369c..0000000
--- a/native_crypto_ios/example/test/widget_test.dart
+++ /dev/null
@@ -1,27 +0,0 @@
-// This is a basic Flutter widget test.
-//
-// To perform an interaction with a widget in your test, use the WidgetTester
-// utility that Flutter provides. For example, you can send tap and scroll
-// gestures. You can also use WidgetTester to find child widgets in the widget
-// tree, read text, and verify that the values of widget properties are correct.
-
-import 'package:flutter/material.dart';
-import 'package:flutter_test/flutter_test.dart';
-
-import 'package:native_crypto_ios_example/main.dart';
-
-void main() {
- testWidgets('Verify Platform version', (WidgetTester tester) async {
- // Build our app and trigger a frame.
- await tester.pumpWidget(const MyApp());
-
- // Verify that platform version is retrieved.
- expect(
- find.byWidgetPredicate(
- (Widget widget) => widget is Text &&
- widget.data!.startsWith('Running on:'),
- ),
- findsOneWidget,
- );
- });
-}
diff --git a/native_crypto_ios/ios/Classes/Cipher.swift b/native_crypto_ios/ios/Classes/Cipher.swift
deleted file mode 100644
index 7204680..0000000
--- a/native_crypto_ios/ios/Classes/Cipher.swift
+++ /dev/null
@@ -1,53 +0,0 @@
-/**
- * Author: Hugo Pointcheval
- * Email: git@pcl.ovh
- * -----
- * File: Cipher.swift
- * Created Date: 25/12/2021 18:31:28
- * Last Modified: 25/12/2021 18:38:53
- * -----
- * Copyright (c) 2021
- */
-
-import Foundation
-import CryptoKit
-
-class AESCipher {
- /// Encrypts plaintext with key using AES GCM
- @available(iOS 13.0, *)
- static func encrypt(plaintext: Data, key: Data) -> Data? {
- let symmetricKey = SymmetricKey.init(data: key)
- let encrypted = try? AES.GCM.seal(plaintext, using: symmetricKey)
- return encrypted?.combined
- }
-
- /// Decrypts ciphertext with key using AES GCM
- @available(iOS 13.0, *)
- static func decrypt(ciphertext: Data, key: Data) -> Data? {
- let symmetricKey = SymmetricKey.init(data: key)
- let sealedBox = try? AES.GCM.SealedBox(combined: ciphertext)
- if (sealedBox == nil) { return nil }
- let decryptedData = try? AES.GCM.open(sealedBox!, using: symmetricKey)
- return decryptedData
- }
-}
-
-class CHACHACipher {
- /// Encrypts plaintext with key using CHACHAPOLY
- @available(iOS 13.0, *)
- static func encrypt(plaintext: Data, key: Data) -> Data? {
- let symmetricKey = SymmetricKey.init(data: key)
- let encrypted = try? ChaChaPoly.seal(plaintext, using: symmetricKey)
- return encrypted?.combined
- }
-
- /// Decrypts ciphertext with key using CHACHAPOLY
- @available(iOS 13.0, *)
- static func decrypt(ciphertext: Data, key: Data) -> Data? {
- let symmetricKey = SymmetricKey.init(data: key)
- let sealedBox = try? ChaChaPoly.SealedBox(combined: ciphertext)
- if (sealedBox == nil) { return nil }
- let decryptedData = try? ChaChaPoly.open(sealedBox!, using: symmetricKey)
- return decryptedData
- }
-}
diff --git a/native_crypto_ios/ios/Classes/Hash.swift b/native_crypto_ios/ios/Classes/Hash.swift
deleted file mode 100644
index 94990ec..0000000
--- a/native_crypto_ios/ios/Classes/Hash.swift
+++ /dev/null
@@ -1,43 +0,0 @@
-/**
- * Author: Hugo Pointcheval
- * Email: git@pcl.ovh
- * -----
- * File: Hash.swift
- * Created Date: 25/12/2021 18:31:11
- * Last Modified: 25/12/2021 18:38:20
- * -----
- * Copyright (c) 2021
- */
-
-import Foundation
-import CommonCrypto
-import CryptoKit
-
-enum HashAlgorithm: String {
- case HashSHA256 = "sha256"
- case HashSHA384 = "sha384"
- case HashSHA512 = "sha512"
-
- var commonCrypto: UInt32 {
- switch self {
- case .HashSHA256: return CCPBKDFAlgorithm(kCCPRFHmacAlgSHA256)
- case .HashSHA384: return CCPBKDFAlgorithm(kCCPRFHmacAlgSHA384)
- case .HashSHA512: return CCPBKDFAlgorithm(kCCPRFHmacAlgSHA512)
- }
- }
-}
-
-@available(iOS 13.0, *)
-class Hash {
- /// Hash a message with a specified HashAlgorithm
- static func digest(data: Data, algorithm: HashAlgorithm) -> Data {
- switch algorithm {
- case .HashSHA256:
- return Data(SHA256.hash(data: data))
- case .HashSHA384:
- return Data(SHA384.hash(data: data))
- case .HashSHA512:
- return Data(SHA512.hash(data: data))
- }
- }
-}
diff --git a/native_crypto_ios/ios/Classes/KEM.swift b/native_crypto_ios/ios/Classes/KEM.swift
deleted file mode 100644
index cf3a27b..0000000
--- a/native_crypto_ios/ios/Classes/KEM.swift
+++ /dev/null
@@ -1,78 +0,0 @@
-/**
- * Author: Hugo Pointcheval
- * Email: git@pcl.ovh
- * -----
- * File: KEM.swift
- * Created Date: 25/12/2021 18:31:48
- * Last Modified: 25/12/2021 18:40:00
- * -----
- * Copyright (c) 2021
- */
-
-import Foundation
-import CryptoKit
-
-class KeyPair {
- /// Generate a keypair.
- @available(iOS 13.0, *)
- static func fromCurve() -> Data {
- let sk = P256.KeyAgreement.PrivateKey()
- var kp = sk.rawRepresentation
- kp.append(contentsOf: sk.publicKey.rawRepresentation)
- return kp;
- }
-
- /// Import private key from Data
- @available(iOS 13.0, *)
- static func importPrivateKey(privateKey: Data) throws -> P256.KeyAgreement.PrivateKey {
- let sk = try P256.KeyAgreement.PrivateKey(rawRepresentation: privateKey)
-
- return sk;
- }
-
- /// Import public key from Data
- @available(iOS 13.0, *)
- static func importPublicKey(publicKey: Data) throws -> P256.KeyAgreement.PublicKey {
- let pk = try P256.KeyAgreement.PublicKey(rawRepresentation: publicKey)
-
- return pk;
- }
-}
-
-class ECDH {
- /// Generate a shared secret with your private key and other party public key.
- @available(iOS 13.0, *)
- static func generateSharedSecretKey(salt: Data, hash: HashAlgorithm, keyBytesCount: Int ,privateKey: Data, publicKey: Data) -> Data? {
- let sk = try? KeyPair.importPrivateKey(privateKey: privateKey)
- if (sk == nil) {return nil}
-
- let pk = try? KeyPair.importPublicKey(publicKey: publicKey)
- if (pk == nil) {return nil}
-
- let secret = try? sk!.sharedSecretFromKeyAgreement(with: pk!)
-
- switch hash {
- case .HashSHA256:
- let key = secret?.hkdfDerivedSymmetricKey(using: SHA256.self, salt: salt, sharedInfo: Data(), outputByteCount: keyBytesCount)
- if (key == nil) {
- return nil
- } else {
- return Key.toBytes(key: key!)
- }
- case .HashSHA384:
- let key = secret?.hkdfDerivedSymmetricKey(using: SHA384.self, salt: salt, sharedInfo: Data(), outputByteCount: keyBytesCount)
- if (key == nil) {
- return nil
- } else {
- return Key.toBytes(key: key!)
- }
- case .HashSHA512:
- let key = secret?.hkdfDerivedSymmetricKey(using: SHA512.self, salt: salt, sharedInfo: Data(), outputByteCount: keyBytesCount)
- if (key == nil) {
- return nil
- } else {
- return Key.toBytes(key: key!)
- }
- }
- }
-}
diff --git a/native_crypto_ios/ios/Classes/Key.swift b/native_crypto_ios/ios/Classes/Key.swift
deleted file mode 100644
index b113df5..0000000
--- a/native_crypto_ios/ios/Classes/Key.swift
+++ /dev/null
@@ -1,62 +0,0 @@
-/**
- * Author: Hugo Pointcheval
- * Email: git@pcl.ovh
- * -----
- * File: KDF.swift
- * Created Date: 25/12/2021 17:45:28
- * Last Modified: 25/12/2021 17:45:38
- * -----
- * Copyright (c) 2021
- */
-
-import Foundation
-import CryptoKit
-import CommonCrypto
-
-class Key {
- /// Generate secret key of a specified length
- @available(iOS 13.0, *)
- static func fromSecureRandom(bitsCount : Int) -> Data {
- let symmetricKey = SymmetricKey.init(size: SymmetricKeySize(bitCount: bitsCount))
- return toBytes(key: symmetricKey)
- }
-
- /// Encode key as Data
- @available(iOS 13.0, *)
- static func toBytes(key: SymmetricKey) -> Data {
- let keyBytes = key.withUnsafeBytes
- {
- return Data(Array($0))
- }
- return keyBytes
- }
-
- /// Derive a new secret key with PBKDF2 algorithm
- static func fromPBKDF2(password: String, salt: String, keyBytesCount: Int, iterations: Int, algorithm: HashAlgorithm) -> Data? {
- let passwordData = password.data(using: .utf8)!
- let saltData = salt.data(using: .utf8)!
-
- var derivedKeyData = Data(repeating: 0, count: keyBytesCount)
- let localDerivedKeyData = derivedKeyData
-
- let status = derivedKeyData.withUnsafeMutableBytes { (derivedKeyBytes: UnsafeMutableRawBufferPointer) in
- saltData.withUnsafeBytes { (saltBytes: UnsafeRawBufferPointer) in
- CCKeyDerivationPBKDF(
- CCPBKDFAlgorithm(kCCPBKDF2),
- password,
- passwordData.count,
- saltBytes.bindMemory(to: UInt8.self).baseAddress,
- saltData.count,
- algorithm.commonCrypto,
- UInt32(iterations),
- derivedKeyBytes.bindMemory(to: UInt8.self).baseAddress,
- localDerivedKeyData.count)
- }
- }
- if (status != kCCSuccess) {
- return nil;
- }
-
- return derivedKeyData
- }
-}
diff --git a/native_crypto_ios/ios/Classes/SwiftNativeCryptoIosPlugin.swift b/native_crypto_ios/ios/Classes/SwiftNativeCryptoIosPlugin.swift
deleted file mode 100644
index 00fdbb7..0000000
--- a/native_crypto_ios/ios/Classes/SwiftNativeCryptoIosPlugin.swift
+++ /dev/null
@@ -1,95 +0,0 @@
-import Flutter
-import UIKit
-
-@available(iOS 13.0, *)
-public class SwiftNativeCryptoIosPlugin: NSObject, FlutterPlugin {
- public static func register(with registrar: FlutterPluginRegistrar) {
- let channel = FlutterMethodChannel(name: "plugins.hugop.cl/native_crypto", binaryMessenger: registrar.messenger())
- let instance = SwiftNativeCryptoIosPlugin()
- registrar.addMethodCallDelegate(instance, channel: channel)
- }
-
- public func handle(_ call: FlutterMethodCall, result: @escaping FlutterResult) {
- switch call.method {
- case "digest":
- let args : NSDictionary = call.arguments as! NSDictionary
-
- let data : Data = (args["data"] as! FlutterStandardTypedData).data
- let algo : String = args["algorithm"] as! String
- let algorithm : HashAlgorithm? = HashAlgorithm.init(rawValue: algo)
- // TODO(hpcl): check if algorithm is null
- // TODO(hpcl): check if digest is null
- result(FlutterStandardTypedData.init(bytes: Hash.digest(data: data, algorithm: algorithm!)))
- case "generateSecretKey":
- let args : NSDictionary = call.arguments as! NSDictionary
-
- let bitsCount : NSNumber = args["bitsCount"] as! NSNumber
- // TODO(hpcl): check if secure random is null
- result(FlutterStandardTypedData.init(bytes: Key.fromSecureRandom(bitsCount: bitsCount.intValue)))
- case "generateKeyPair":
- result(FlutterStandardTypedData.init(bytes: KeyPair.fromCurve()))
- case "pbkdf2":
- let args : NSDictionary = call.arguments as! NSDictionary
-
- let password : String = args["password"] as! String
- let salt : String = args["salt"] as! String
- let keyBytesCount : NSNumber = args["keyBytesCount"] as! NSNumber
- let iterations : NSNumber = args["iterations"] as! NSNumber
- let algo : String = args["algorithm"] as! String
- let algorithm : HashAlgorithm? = HashAlgorithm.init(rawValue: algo)
- // TODO(hpcl): check if algorithm is null
- // TODO(hpcl): check if derivation is null
- result(FlutterStandardTypedData.init(bytes: Key.fromPBKDF2(password: password, salt: salt, keyBytesCount: keyBytesCount.intValue, iterations: iterations.intValue, algorithm: algorithm!)!))
- case "encrypt":
- let args : NSDictionary = call.arguments as! NSDictionary
-
- let data : Data = (args["data"] as! FlutterStandardTypedData).data
- let key : Data = (args["key"] as! FlutterStandardTypedData).data
- let algo : String = args["algorithm"] as! String
- // TODO(hpcl): check if algorithm is null
- // TODO(hpcl): check if ciphertext is null
- var ciphertext : Data
- switch algo {
- case "aes":
- ciphertext = AESCipher.encrypt(plaintext: data, key: key)!
- case "chachapoly":
- ciphertext = CHACHACipher.encrypt(plaintext: data, key: key)!
- default:
- ciphertext = Data.init();
- }
- result(FlutterStandardTypedData.init(bytes: ciphertext))
- case "decrypt":
- let args : NSDictionary = call.arguments as! NSDictionary
-
- let data : Data = (args["data"] as! FlutterStandardTypedData).data
- let key : Data = (args["key"] as! FlutterStandardTypedData).data
- let algo : String = args["algorithm"] as! String
- // TODO(hpcl): check if algorithm is null
- // TODO(hpcl): check if ciphertext is null
- var ciphertext : Data
- switch algo {
- case "aes":
- ciphertext = AESCipher.decrypt(ciphertext: data, key: key)!
- case "chachapoly":
- ciphertext = CHACHACipher.decrypt(ciphertext: data, key: key)!
- default:
- ciphertext = Data.init();
- }
- result(FlutterStandardTypedData.init(bytes: ciphertext))
- case "generateSharedSecretKey":
- let args : NSDictionary = call.arguments as! NSDictionary
-
- let salt : Data = (args["salt"] as! FlutterStandardTypedData).data
- let keyBytesCount : NSNumber = args["keyBytesCount"] as! NSNumber
- let ephemeralPrivateKey : Data = (args["ephemeralPrivateKey"] as! FlutterStandardTypedData).data
- let otherPublicKey : Data = (args["otherPublicKey"] as! FlutterStandardTypedData).data
- let hkdfAlgorithm : String = args["hkdfAlgorithm"] as! String
- let algorithm : HashAlgorithm? = HashAlgorithm.init(rawValue: hkdfAlgorithm)
- // TODO(hpcl): check if algorithm is null
- // TODO(hpcl): check if generated key is null
- result(FlutterStandardTypedData.init(bytes: ECDH.generateSharedSecretKey(salt: salt, hash: algorithm!, keyBytesCount: keyBytesCount.intValue, privateKey: ephemeralPrivateKey, publicKey: otherPublicKey)!))
-
- default: result(FlutterMethodNotImplemented)
- }
- }
-}
diff --git a/native_crypto_platform_interface/CHANGELOG.md b/native_crypto_platform_interface/CHANGELOG.md
deleted file mode 100644
index 41cc7d8..0000000
--- a/native_crypto_platform_interface/CHANGELOG.md
+++ /dev/null
@@ -1,3 +0,0 @@
-## 0.0.1
-
-* TODO: Describe initial release.
diff --git a/native_crypto_platform_interface/LICENSE b/native_crypto_platform_interface/LICENSE
deleted file mode 100644
index ba75c69..0000000
--- a/native_crypto_platform_interface/LICENSE
+++ /dev/null
@@ -1 +0,0 @@
-TODO: Add your license here.
diff --git a/native_crypto_platform_interface/README.md b/native_crypto_platform_interface/README.md
deleted file mode 100644
index 7190aa2..0000000
--- a/native_crypto_platform_interface/README.md
+++ /dev/null
@@ -1,18 +0,0 @@
-# native_crypto_platform_interface
-
-A new flutter plugin project.
-
-## Getting Started
-
-This project is a starting point for a Flutter
-[plug-in package](https://flutter.dev/developing-packages/),
-a specialized package that includes platform-specific implementation code for
-Android and/or iOS.
-
-For help getting started with Flutter, view our
-[online documentation](https://flutter.dev/docs), which offers tutorials,
-samples, guidance on mobile development, and a full API reference.
-
-The plugin project was generated without specifying the `--platforms` flag, no platforms are currently supported.
-To add platforms, run `flutter create -t plugin --platforms .` under the same
-directory. You can also find a detailed instruction on how to add platforms in the `pubspec.yaml` at https://flutter.dev/docs/development/packages-and-plugins/developing-packages#plugin-platforms.
diff --git a/native_crypto_platform_interface/analysis_options.yaml b/native_crypto_platform_interface/analysis_options.yaml
deleted file mode 100644
index a5744c1..0000000
--- a/native_crypto_platform_interface/analysis_options.yaml
+++ /dev/null
@@ -1,4 +0,0 @@
-include: package:flutter_lints/flutter.yaml
-
-# Additional information about this file can be found at
-# https://dart.dev/guides/language/analysis-options
diff --git a/native_crypto_platform_interface/lib/src/method_channel_native_crypto.dart b/native_crypto_platform_interface/lib/src/method_channel_native_crypto.dart
deleted file mode 100644
index 3cab922..0000000
--- a/native_crypto_platform_interface/lib/src/method_channel_native_crypto.dart
+++ /dev/null
@@ -1,107 +0,0 @@
-// Author: Hugo Pointcheval
-// Email: git@pcl.ovh
-// -----
-// File: native_crypto_method_channel.dart
-// Created Date: 25/12/2021 16:58:04
-// Last Modified: 25/12/2021 18:58:53
-// -----
-// Copyright (c) 2021
-
-import 'dart:typed_data';
-
-import 'package:flutter/foundation.dart';
-import 'package:flutter/services.dart';
-
-import '../native_crypto_platform_interface.dart';
-
-/// An implementation of [NativeCryptoPlatform] that uses method channels.
-class MethodChannelNativeCrypto extends NativeCryptoPlatform {
- /// The method channel used to interact with the native platform.
- @visibleForTesting
- MethodChannel methodChannel =
- const MethodChannel('plugins.hugop.cl/native_crypto');
-
- @override
- Future digest(Uint8List data, String algorithm) {
- return methodChannel.invokeMethod(
- 'digest',
- {
- 'data': data,
- 'algorithm': algorithm,
- },
- );
- }
-
- @override
- Future generateSecretKey(int bitsCount) {
- return methodChannel.invokeMethod(
- 'generateSecretKey',
- {
- 'bitsCount': bitsCount,
- },
- );
- }
-
- @override
- Future generateKeyPair() {
- return methodChannel.invokeMethod('generateKeyPair');
- }
-
- @override
- Future pbkdf2(String password, String salt, int keyBytesCount,
- int iterations, String algorithm) {
- return methodChannel.invokeMethod(
- 'pbkdf2',
- {
- 'password': password,
- 'salt': salt,
- 'keyBytesCount': keyBytesCount,
- 'iterations': iterations,
- 'algorithm': algorithm,
- },
- );
- }
-
- @override
- Future encrypt(Uint8List data, Uint8List key, String algorithm) {
- return methodChannel.invokeMethod(
- 'encrypt',
- {
- 'data': data,
- 'key': key,
- 'algorithm': algorithm,
- },
- );
- }
-
- @override
- Future decrypt(Uint8List data, Uint8List key, String algorithm) {
- return methodChannel.invokeMethod(
- 'decrypt',
- {
- 'data': data,
- 'key': key,
- 'algorithm': algorithm,
- },
- );
- }
-
- @override
- Future generateSharedSecretKey(
- Uint8List salt,
- int keyBytesCount,
- Uint8List ephemeralPrivateKey,
- Uint8List otherPublicKey,
- String hkdfAlgorithm) {
- return methodChannel.invokeMethod(
- 'generateSharedSecretKey',
- {
- 'salt': salt,
- 'keyBytesCount': keyBytesCount,
- 'ephemeralPrivateKey': ephemeralPrivateKey,
- 'otherPublicKey': otherPublicKey,
- 'hkdfAlgorithm': hkdfAlgorithm,
- },
- );
- }
-}
diff --git a/native_crypto_platform_interface/lib/src/platform_interface.dart b/native_crypto_platform_interface/lib/src/platform_interface.dart
deleted file mode 100644
index d0585c9..0000000
--- a/native_crypto_platform_interface/lib/src/platform_interface.dart
+++ /dev/null
@@ -1,97 +0,0 @@
-// Author: Hugo Pointcheval
-// Email: git@pcl.ovh
-// -----
-// File: platform_interface.dart
-// Created Date: 25/12/2021 16:52:56
-// Last Modified: 25/12/2021 16:53:36
-// -----
-// Copyright (c) 2021
-
-import 'package:meta/meta.dart';
-
-/// Base class for platform interfaces.
-///
-/// Provides a static helper method for ensuring that platform interfaces are
-/// implemented using `extends` instead of `implements`.
-///
-/// Platform interface classes are expected to have a private static token object which will be
-/// be passed to [verifyToken] along with a platform interface object for verification.
-///
-/// Sample usage:
-///
-/// ```dart
-/// abstract class UrlLauncherPlatform extends PlatformInterface {
-/// UrlLauncherPlatform() : super(token: _token);
-///
-/// static UrlLauncherPlatform _instance = MethodChannelUrlLauncher();
-///
-/// static const Object _token = Object();
-///
-/// static UrlLauncherPlatform get instance => _instance;
-///
-/// /// Platform-specific plugins should set this with their own platform-specific
-/// /// class that extends [UrlLauncherPlatform] when they register themselves.
-/// static set instance(UrlLauncherPlatform instance) {
-/// PlatformInterface.verifyToken(instance, _token);
-/// _instance = instance;
-/// }
-///
-/// }
-/// ```
-///
-/// Mockito mocks of platform interfaces will fail the verification, in test code only it is possible
-/// to include the [MockPlatformInterfaceMixin] for the verification to be temporarily disabled. See
-/// [MockPlatformInterfaceMixin] for a sample of using Mockito to mock a platform interface.
-abstract class PlatformInterface {
- /// Pass a private, class-specific `const Object()` as the `token`.
- PlatformInterface({required Object token}) : _instanceToken = token;
-
- final Object? _instanceToken;
-
- /// Ensures that the platform instance has a token that matches the
- /// provided token and throws [AssertionError] if not.
- ///
- /// This is used to ensure that implementers are using `extends` rather than
- /// `implements`.
- ///
- /// Subclasses of [MockPlatformInterfaceMixin] are assumed to be valid in debug
- /// builds.
- ///
- /// This is implemented as a static method so that it cannot be overridden
- /// with `noSuchMethod`.
- static void verifyToken(PlatformInterface instance, Object token) {
- if (instance is MockPlatformInterfaceMixin) {
- bool assertionsEnabled = false;
- assert(() {
- assertionsEnabled = true;
- return true;
- }());
- if (!assertionsEnabled) {
- throw AssertionError(
- '`MockPlatformInterfaceMixin` is not intended for use in release builds.');
- }
- return;
- }
- if (!identical(token, instance._instanceToken)) {
- throw AssertionError(
- 'Platform interfaces must not be implemented with `implements`');
- }
- }
-}
-
-/// A [PlatformInterface] mixin that can be combined with mockito's `Mock`.
-///
-/// It passes the [PlatformInterface.verifyToken] check even though it isn't
-/// using `extends`.
-///
-/// This class is intended for use in tests only.
-///
-/// Sample usage (assuming UrlLauncherPlatform extends [PlatformInterface]:
-///
-/// ```dart
-/// class UrlLauncherPlatformMock extends Mock
-/// with MockPlatformInterfaceMixin
-/// implements UrlLauncherPlatform {}
-/// ```
-@visibleForTesting
-abstract class MockPlatformInterfaceMixin implements PlatformInterface {}
\ No newline at end of file
diff --git a/native_crypto_platform_interface/pubspec.yaml b/native_crypto_platform_interface/pubspec.yaml
deleted file mode 100644
index 017ea35..0000000
--- a/native_crypto_platform_interface/pubspec.yaml
+++ /dev/null
@@ -1,17 +0,0 @@
-name: native_crypto_platform_interface
-description: A common interface for NativeCrypto plugin.
-version: 0.0.7
-
-environment:
- sdk: ">=2.15.0 <3.0.0"
- flutter: ">=2.5.0"
-
-dependencies:
- flutter:
- sdk: flutter
-
-dev_dependencies:
- flutter_test:
- sdk: flutter
-
- flutter_lints: ^1.0.4
\ No newline at end of file
diff --git a/native_crypto_platform_interface/test/native_crypto_platform_interface_test.dart b/native_crypto_platform_interface/test/native_crypto_platform_interface_test.dart
deleted file mode 100644
index e69de29..0000000
diff --git a/native_crypto/.metadata b/packages/native_crypto/.metadata
similarity index 100%
rename from native_crypto/.metadata
rename to packages/native_crypto/.metadata
diff --git a/packages/native_crypto/CHANGELOG.md b/packages/native_crypto/CHANGELOG.md
new file mode 100644
index 0000000..55a24cb
--- /dev/null
+++ b/packages/native_crypto/CHANGELOG.md
@@ -0,0 +1,45 @@
+## 0.1.1
+
+ - **REFACTOR**: change file organization.
+ - **PERF**: x10 perfomance improvement on android with better list management.
+ - **FIX**: benchmark output.
+ - **FIX**: update and fix code.
+ - **FEAT**: export new exceptions.
+ - **FEAT**: add PointyCastle benchmark.
+ - **DOCS**: add link to readme file.
+
+## 0.1.0
+
+> Breaking changes !
+
+* Follow **Federated Plugin** Flutter standard.
+
+## 0.0.6
+
+* Add KeyPair generation.
+* Rework exposed API.
+
+## 0.0.5
+
+* New API.
+* Add digest support.
+* Clean platform specific code base.
+
+## 0.0.4
+
+* Improve AES.
+
+## 0.0.3
+
+* Add PBKDF2 support.
+* Add exceptions.
+* Improve documentation.
+
+## 0.0.2
+
+* Add different key size support.
+* Improve performances.
+
+## 0.0.1
+
+* First AES cross-platform encryption & decryption implementation.
diff --git a/packages/native_crypto/LICENSE b/packages/native_crypto/LICENSE
new file mode 100644
index 0000000..082d930
--- /dev/null
+++ b/packages/native_crypto/LICENSE
@@ -0,0 +1,23 @@
+NativeCrypto
+
+MIT License
+
+Copyright (c) 2019 - 2022 Hugo Pointcheval
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.
\ No newline at end of file
diff --git a/packages/native_crypto/README.md b/packages/native_crypto/README.md
new file mode 100644
index 0000000..507b7ec
--- /dev/null
+++ b/packages/native_crypto/README.md
@@ -0,0 +1,133 @@
+
+
+
Fast and powerful cryptographic functions for Flutter.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+---
+
+[[Changelog]](./CHANGELOG.md) | [[License]](./LICENSE)
+
+---
+
+## About
+
+The goal of this plugin is to provide a fast and powerful cryptographic functions by calling native libraries. On Android, it uses [javax.cypto](https://developer.android.com/reference/javax/crypto/package-summary), and on iOS, it uses [CommonCrypto](https://opensource.apple.com/source/CommonCrypto/) and [CryptoKit](https://developer.apple.com/documentation/cryptokit/)
+
+I started this projet because I wanted to add cryptographic functions on a Flutter app. But I faced a problem with the well-known [Pointy Castle](https://pub.dev/packages/pointycastle) library: the performance was very poor. Here some benchmarks and comparison:
+
+![](resources/benchmarks.png)
+
+For comparison, on a *iPhone 13*, you can encrypt/decrypt a message of **2MiB** in **~5.6s** with PointyCastle and in **~40ms** with NativeCrypto. And on an *OnePlus 5*, you can encrypt/decrypt a message of **50MiB** in **~6min30** with PointyCastle and in less than **~1s** with NativeCrypto.
+
+In short, NativeCrypto is incomparable with PointyCastle.
+
+## Usage
+
+First, check compatibility with your targets.
+
+| iOS | Android | MacOS | Linux | Windows | Web |
+| --- | ------- | ----- | ----- | ------- | --- |
+| ✅ | ✅ | ❌ | ❌ | ❌ | ❌ |
+
+#### Hash
+
+To digest a message, you can use the following function:
+
+```dart
+Uint8List hash = await HashAlgorithm.sha256.digest(message);
+```
+
+> In NativeCrypto, you can use the following hash functions: SHA-256, SHA-384, SHA-512
+
+#### Keys
+
+You can build a `SecretKey` from a utf8, base64, base16 (hex) strings or raw bytes. You can also generate a SecretKey from secure random.
+
+```dart
+SecretKey secretKey = SecretKey(Uint8List.fromList([0x73, 0x65, 0x63, 0x72, 0x65, 0x74]));
+SecretKey secretKey = SecretKey.fromUtf8('secret');
+SecretKey secretKey = SecretKey.fromBase64('c2VjcmV0');
+SecretKey secretKey = SecretKey.fromBase16('63657274');
+SecretKey secretKey = await SecretKey.fromSecureRandom(256);
+```
+
+#### Key derivation
+
+You can derive a `SecretKey` using **PBKDF2**.
+
+First, you need to initialize a `Pbkdf2` object.
+
+```dart
+Pbkdf2 pbkdf2 = Pbkdf2(
+ keyBytesCount: 32,
+ iterations: 1000,
+ algorithm: HashAlgorithm.sha512,
+);
+```
+
+Then, you can derive a `SecretKey` from a password and salt.
+
+```dart
+SecretKey secretKey = await pbkdf2.derive(password: password, salt: 'salt');
+```
+
+> In NativeCrypto, you can use the following key derivation function: PBKDF2
+
+#### Cipher
+
+And now, you can use the `SecretKey` to encrypt/decrypt a message.
+
+First, you need to initialize a `Cipher` object.
+
+```dart
+AES cipher = AES(secretKey);
+```
+
+Then, you can encrypt your message.
+
+```dart
+CipherTextWrapper wrapper = await cipher.encrypt(message);
+
+CipherText cipherText = wrapper.unwrap();
+// same as
+CipherText cipherText = wrapper.single;
+
+// or
+
+List cipherTexts = wrapper.unwrap>();
+// same as
+List cipherTexts = wrapper.list;
+```
+
+After an encryption you obtain a `CipherTextWrapper` which contains `CipherText` or `List` depending on the message size. It's up to you to know how to unwrap the `CipherTextWrapper` depending the chunk size you configured.
+
+Uppon receiving encrypted message, you can decrypt it.
+You have to reconstruct the wrapper before decrypting.
+
+```dart
+CipherTextWrapper wrapper = CipherTextWrapper.fromBytes(
+ data,
+ ivLength: AESMode.gcm.ivLength,
+ tagLength: AESMode.gcm.tagLength,
+);
+```
+
+Then, you can decrypt your message.
+
+```dart
+Uint8List message = await cipher.decrypt(wrapper);
+```
\ No newline at end of file
diff --git a/packages/native_crypto/analysis_options.yaml b/packages/native_crypto/analysis_options.yaml
new file mode 100644
index 0000000..db48808
--- /dev/null
+++ b/packages/native_crypto/analysis_options.yaml
@@ -0,0 +1 @@
+include: package:wyatt_analysis/analysis_options.flutter.experimental.yaml
\ No newline at end of file
diff --git a/native_crypto/example/.gitignore b/packages/native_crypto/example/.gitignore
similarity index 100%
rename from native_crypto/example/.gitignore
rename to packages/native_crypto/example/.gitignore
diff --git a/native_crypto/example/.metadata b/packages/native_crypto/example/.metadata
similarity index 100%
rename from native_crypto/example/.metadata
rename to packages/native_crypto/example/.metadata
diff --git a/native_crypto/example/README.md b/packages/native_crypto/example/README.md
similarity index 100%
rename from native_crypto/example/README.md
rename to packages/native_crypto/example/README.md
diff --git a/native_crypto/example/analysis_options.yaml b/packages/native_crypto/example/analysis_options.yaml
similarity index 100%
rename from native_crypto/example/analysis_options.yaml
rename to packages/native_crypto/example/analysis_options.yaml
diff --git a/native_crypto/example/android/.gitignore b/packages/native_crypto/example/android/.gitignore
similarity index 100%
rename from native_crypto/example/android/.gitignore
rename to packages/native_crypto/example/android/.gitignore
diff --git a/native_crypto/example/android/app/build.gradle b/packages/native_crypto/example/android/app/build.gradle
similarity index 97%
rename from native_crypto/example/android/app/build.gradle
rename to packages/native_crypto/example/android/app/build.gradle
index 803881a..15632c2 100644
--- a/native_crypto/example/android/app/build.gradle
+++ b/packages/native_crypto/example/android/app/build.gradle
@@ -44,7 +44,7 @@ android {
defaultConfig {
// TODO: Specify your own unique Application ID (https://developer.android.com/studio/build/application-id.html).
applicationId "fr.pointcheval.native_crypto_example"
- minSdkVersion flutter.minSdkVersion
+ minSdkVersion 26
targetSdkVersion flutter.targetSdkVersion
versionCode flutterVersionCode.toInteger()
versionName flutterVersionName
diff --git a/native_crypto/example/android/app/src/debug/AndroidManifest.xml b/packages/native_crypto/example/android/app/src/debug/AndroidManifest.xml
similarity index 100%
rename from native_crypto/example/android/app/src/debug/AndroidManifest.xml
rename to packages/native_crypto/example/android/app/src/debug/AndroidManifest.xml
diff --git a/native_crypto/example/android/app/src/main/AndroidManifest.xml b/packages/native_crypto/example/android/app/src/main/AndroidManifest.xml
similarity index 100%
rename from native_crypto/example/android/app/src/main/AndroidManifest.xml
rename to packages/native_crypto/example/android/app/src/main/AndroidManifest.xml
diff --git a/native_crypto/example/android/app/src/main/kotlin/fr/pointcheval/native_crypto_example/MainActivity.kt b/packages/native_crypto/example/android/app/src/main/kotlin/fr/pointcheval/native_crypto_example/MainActivity.kt
similarity index 100%
rename from native_crypto/example/android/app/src/main/kotlin/fr/pointcheval/native_crypto_example/MainActivity.kt
rename to packages/native_crypto/example/android/app/src/main/kotlin/fr/pointcheval/native_crypto_example/MainActivity.kt
diff --git a/native_crypto/example/android/app/src/main/res/drawable-v21/launch_background.xml b/packages/native_crypto/example/android/app/src/main/res/drawable-v21/launch_background.xml
similarity index 100%
rename from native_crypto/example/android/app/src/main/res/drawable-v21/launch_background.xml
rename to packages/native_crypto/example/android/app/src/main/res/drawable-v21/launch_background.xml
diff --git a/native_crypto/example/android/app/src/main/res/drawable/launch_background.xml b/packages/native_crypto/example/android/app/src/main/res/drawable/launch_background.xml
similarity index 100%
rename from native_crypto/example/android/app/src/main/res/drawable/launch_background.xml
rename to packages/native_crypto/example/android/app/src/main/res/drawable/launch_background.xml
diff --git a/native_crypto/example/android/app/src/main/res/mipmap-hdpi/ic_launcher.png b/packages/native_crypto/example/android/app/src/main/res/mipmap-hdpi/ic_launcher.png
similarity index 100%
rename from native_crypto/example/android/app/src/main/res/mipmap-hdpi/ic_launcher.png
rename to packages/native_crypto/example/android/app/src/main/res/mipmap-hdpi/ic_launcher.png
diff --git a/native_crypto/example/android/app/src/main/res/mipmap-mdpi/ic_launcher.png b/packages/native_crypto/example/android/app/src/main/res/mipmap-mdpi/ic_launcher.png
similarity index 100%
rename from native_crypto/example/android/app/src/main/res/mipmap-mdpi/ic_launcher.png
rename to packages/native_crypto/example/android/app/src/main/res/mipmap-mdpi/ic_launcher.png
diff --git a/native_crypto/example/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png b/packages/native_crypto/example/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png
similarity index 100%
rename from native_crypto/example/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png
rename to packages/native_crypto/example/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png
diff --git a/native_crypto/example/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png b/packages/native_crypto/example/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png
similarity index 100%
rename from native_crypto/example/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png
rename to packages/native_crypto/example/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png
diff --git a/native_crypto/example/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png b/packages/native_crypto/example/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png
similarity index 100%
rename from native_crypto/example/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png
rename to packages/native_crypto/example/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png
diff --git a/native_crypto/example/android/app/src/main/res/values-night/styles.xml b/packages/native_crypto/example/android/app/src/main/res/values-night/styles.xml
similarity index 100%
rename from native_crypto/example/android/app/src/main/res/values-night/styles.xml
rename to packages/native_crypto/example/android/app/src/main/res/values-night/styles.xml
diff --git a/native_crypto/example/android/app/src/main/res/values/styles.xml b/packages/native_crypto/example/android/app/src/main/res/values/styles.xml
similarity index 100%
rename from native_crypto/example/android/app/src/main/res/values/styles.xml
rename to packages/native_crypto/example/android/app/src/main/res/values/styles.xml
diff --git a/native_crypto/example/android/app/src/profile/AndroidManifest.xml b/packages/native_crypto/example/android/app/src/profile/AndroidManifest.xml
similarity index 100%
rename from native_crypto/example/android/app/src/profile/AndroidManifest.xml
rename to packages/native_crypto/example/android/app/src/profile/AndroidManifest.xml
diff --git a/native_crypto/example/android/build.gradle b/packages/native_crypto/example/android/build.gradle
similarity index 84%
rename from native_crypto/example/android/build.gradle
rename to packages/native_crypto/example/android/build.gradle
index 24047dc..3245887 100644
--- a/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/native_crypto/example/android/gradle.properties b/packages/native_crypto/example/android/gradle.properties
similarity index 100%
rename from native_crypto/example/android/gradle.properties
rename to packages/native_crypto/example/android/gradle.properties
diff --git a/native_crypto/example/android/gradle/wrapper/gradle-wrapper.properties b/packages/native_crypto/example/android/gradle/wrapper/gradle-wrapper.properties
similarity index 93%
rename from native_crypto/example/android/gradle/wrapper/gradle-wrapper.properties
rename to packages/native_crypto/example/android/gradle/wrapper/gradle-wrapper.properties
index bc6a58a..562c5e4 100644
--- a/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/native_crypto/example/android/settings.gradle b/packages/native_crypto/example/android/settings.gradle
similarity index 100%
rename from native_crypto/example/android/settings.gradle
rename to packages/native_crypto/example/android/settings.gradle
diff --git a/native_crypto/example/ios/.gitignore b/packages/native_crypto/example/ios/.gitignore
similarity index 100%
rename from native_crypto/example/ios/.gitignore
rename to packages/native_crypto/example/ios/.gitignore
diff --git a/native_crypto/example/ios/Flutter/AppFrameworkInfo.plist b/packages/native_crypto/example/ios/Flutter/AppFrameworkInfo.plist
similarity index 100%
rename from native_crypto/example/ios/Flutter/AppFrameworkInfo.plist
rename to packages/native_crypto/example/ios/Flutter/AppFrameworkInfo.plist
diff --git a/native_crypto/example/ios/Flutter/Debug.xcconfig b/packages/native_crypto/example/ios/Flutter/Debug.xcconfig
similarity index 100%
rename from native_crypto/example/ios/Flutter/Debug.xcconfig
rename to packages/native_crypto/example/ios/Flutter/Debug.xcconfig
diff --git a/native_crypto/example/ios/Flutter/Release.xcconfig b/packages/native_crypto/example/ios/Flutter/Release.xcconfig
similarity index 100%
rename from native_crypto/example/ios/Flutter/Release.xcconfig
rename to packages/native_crypto/example/ios/Flutter/Release.xcconfig
diff --git a/native_crypto/example/ios/Podfile b/packages/native_crypto/example/ios/Podfile
similarity index 98%
rename from native_crypto/example/ios/Podfile
rename to packages/native_crypto/example/ios/Podfile
index 1e8c3c9..10f3c9b 100644
--- a/native_crypto/example/ios/Podfile
+++ b/packages/native_crypto/example/ios/Podfile
@@ -1,5 +1,5 @@
# Uncomment this line to define a global platform for your project
-# platform :ios, '9.0'
+platform :ios, '13.0'
# CocoaPods analytics sends network stats synchronously affecting flutter build latency.
ENV['COCOAPODS_DISABLE_STATS'] = 'true'
diff --git a/native_crypto_ios/example/ios/Podfile.lock b/packages/native_crypto/example/ios/Podfile.lock
similarity index 73%
rename from native_crypto_ios/example/ios/Podfile.lock
rename to packages/native_crypto/example/ios/Podfile.lock
index d6ba796..3257d42 100644
--- a/native_crypto_ios/example/ios/Podfile.lock
+++ b/packages/native_crypto/example/ios/Podfile.lock
@@ -15,8 +15,8 @@ EXTERNAL SOURCES:
SPEC CHECKSUMS:
Flutter: 50d75fe2f02b26cc09d224853bb45737f8b3214a
- native_crypto_ios: 01f5aa926eb715d08259fd20bb951ba0f69c4e74
+ native_crypto_ios: de03ec2f594e8d41bcba2341b7ad57fd926ada5d
-PODFILE CHECKSUM: aafe91acc616949ddb318b77800a7f51bffa2a4c
+PODFILE CHECKSUM: cc1f88378b4bfcf93a6ce00d2c587857c6008d3b
-COCOAPODS: 1.10.1
+COCOAPODS: 1.11.3
diff --git a/native_crypto_ios/example/ios/Runner.xcodeproj/project.pbxproj b/packages/native_crypto/example/ios/Runner.xcodeproj/project.pbxproj
similarity index 94%
rename from native_crypto_ios/example/ios/Runner.xcodeproj/project.pbxproj
rename to packages/native_crypto/example/ios/Runner.xcodeproj/project.pbxproj
index 7156cef..8c503eb 100644
--- a/native_crypto_ios/example/ios/Runner.xcodeproj/project.pbxproj
+++ b/packages/native_crypto/example/ios/Runner.xcodeproj/project.pbxproj
@@ -8,8 +8,8 @@
/* Begin PBXBuildFile section */
1498D2341E8E89220040F4C2 /* GeneratedPluginRegistrant.m in Sources */ = {isa = PBXBuildFile; fileRef = 1498D2331E8E89220040F4C2 /* GeneratedPluginRegistrant.m */; };
- 20AC864B3037BB896BD381B1 /* Pods_Runner.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 056766980834B5FAC1C4D331 /* Pods_Runner.framework */; };
3B3967161E833CAA004F5970 /* AppFrameworkInfo.plist in Resources */ = {isa = PBXBuildFile; fileRef = 3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */; };
+ 57C8B66CEF3FCADD27359CF2 /* Pods_Runner.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 9B565CC9BF59F330E881E6A5 /* Pods_Runner.framework */; };
74858FAF1ED2DC5600515810 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 74858FAE1ED2DC5600515810 /* AppDelegate.swift */; };
97C146FC1CF9000F007C117D /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FA1CF9000F007C117D /* Main.storyboard */; };
97C146FE1CF9000F007C117D /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FD1CF9000F007C117D /* Assets.xcassets */; };
@@ -30,12 +30,12 @@
/* End PBXCopyFilesBuildPhase section */
/* Begin PBXFileReference section */
- 056766980834B5FAC1C4D331 /* Pods_Runner.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_Runner.framework; sourceTree = BUILT_PRODUCTS_DIR; };
- 1180301722C337B6C625E46F /* Pods-Runner.profile.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.profile.xcconfig"; path = "Target Support Files/Pods-Runner/Pods-Runner.profile.xcconfig"; sourceTree = ""; };
1498D2321E8E86230040F4C2 /* GeneratedPluginRegistrant.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = GeneratedPluginRegistrant.h; sourceTree = ""; };
1498D2331E8E89220040F4C2 /* GeneratedPluginRegistrant.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GeneratedPluginRegistrant.m; sourceTree = ""; };
- 2A0F0FD6D80A80663D317892 /* Pods-Runner.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.release.xcconfig"; path = "Target Support Files/Pods-Runner/Pods-Runner.release.xcconfig"; sourceTree = ""; };
+ 2ABDB9EE0C984D50A4E8A819 /* Pods-Runner.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.release.xcconfig"; path = "Target Support Files/Pods-Runner/Pods-Runner.release.xcconfig"; sourceTree = ""; };
3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; name = AppFrameworkInfo.plist; path = Flutter/AppFrameworkInfo.plist; sourceTree = ""; };
+ 4276EDF2B0F07350DCE3D5A1 /* Pods-Runner.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.debug.xcconfig"; path = "Target Support Files/Pods-Runner/Pods-Runner.debug.xcconfig"; sourceTree = ""; };
+ 5CD4F461EBFD40A270B90468 /* Pods-Runner.profile.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.profile.xcconfig"; path = "Target Support Files/Pods-Runner/Pods-Runner.profile.xcconfig"; sourceTree = ""; };
74858FAD1ED2DC5600515810 /* Runner-Bridging-Header.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "Runner-Bridging-Header.h"; sourceTree = ""; };
74858FAE1ED2DC5600515810 /* AppDelegate.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = ""; };
7AFA3C8E1D35360C0083082E /* Release.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; name = Release.xcconfig; path = Flutter/Release.xcconfig; sourceTree = ""; };
@@ -46,7 +46,7 @@
97C146FD1CF9000F007C117D /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = ""; };
97C147001CF9000F007C117D /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/LaunchScreen.storyboard; sourceTree = ""; };
97C147021CF9000F007C117D /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; };
- EC40AF9C4AC2A38A0B8CC0E6 /* Pods-Runner.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.debug.xcconfig"; path = "Target Support Files/Pods-Runner/Pods-Runner.debug.xcconfig"; sourceTree = ""; };
+ 9B565CC9BF59F330E881E6A5 /* Pods_Runner.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_Runner.framework; sourceTree = BUILT_PRODUCTS_DIR; };
/* End PBXFileReference section */
/* Begin PBXFrameworksBuildPhase section */
@@ -54,19 +54,19 @@
isa = PBXFrameworksBuildPhase;
buildActionMask = 2147483647;
files = (
- 20AC864B3037BB896BD381B1 /* Pods_Runner.framework in Frameworks */,
+ 57C8B66CEF3FCADD27359CF2 /* Pods_Runner.framework in Frameworks */,
);
runOnlyForDeploymentPostprocessing = 0;
};
/* End PBXFrameworksBuildPhase section */
/* Begin PBXGroup section */
- 3024D600AF0E0DED3BB44E03 /* Pods */ = {
+ 56AFD4323C9A594E66DE3CA2 /* Pods */ = {
isa = PBXGroup;
children = (
- EC40AF9C4AC2A38A0B8CC0E6 /* Pods-Runner.debug.xcconfig */,
- 2A0F0FD6D80A80663D317892 /* Pods-Runner.release.xcconfig */,
- 1180301722C337B6C625E46F /* Pods-Runner.profile.xcconfig */,
+ 4276EDF2B0F07350DCE3D5A1 /* Pods-Runner.debug.xcconfig */,
+ 2ABDB9EE0C984D50A4E8A819 /* Pods-Runner.release.xcconfig */,
+ 5CD4F461EBFD40A270B90468 /* Pods-Runner.profile.xcconfig */,
);
name = Pods;
path = Pods;
@@ -89,8 +89,8 @@
9740EEB11CF90186004384FC /* Flutter */,
97C146F01CF9000F007C117D /* Runner */,
97C146EF1CF9000F007C117D /* Products */,
- 3024D600AF0E0DED3BB44E03 /* Pods */,
- F589250F1A900F4BC6E4BB56 /* Frameworks */,
+ 56AFD4323C9A594E66DE3CA2 /* Pods */,
+ CECC25F8D34DF7912A93B0E6 /* Frameworks */,
);
sourceTree = "";
};
@@ -117,10 +117,10 @@
path = Runner;
sourceTree = "";
};
- F589250F1A900F4BC6E4BB56 /* Frameworks */ = {
+ CECC25F8D34DF7912A93B0E6 /* Frameworks */ = {
isa = PBXGroup;
children = (
- 056766980834B5FAC1C4D331 /* Pods_Runner.framework */,
+ 9B565CC9BF59F330E881E6A5 /* Pods_Runner.framework */,
);
name = Frameworks;
sourceTree = "";
@@ -132,14 +132,14 @@
isa = PBXNativeTarget;
buildConfigurationList = 97C147051CF9000F007C117D /* Build configuration list for PBXNativeTarget "Runner" */;
buildPhases = (
- CE2C3E978245C5FF80E431AC /* [CP] Check Pods Manifest.lock */,
+ C54B0935BA386F7769969821 /* [CP] Check Pods Manifest.lock */,
9740EEB61CF901F6004384FC /* Run Script */,
97C146EA1CF9000F007C117D /* Sources */,
97C146EB1CF9000F007C117D /* Frameworks */,
97C146EC1CF9000F007C117D /* Resources */,
9705A1C41CF9048500538489 /* Embed Frameworks */,
3B06AD1E1E4923F5004D2608 /* Thin Binary */,
- ED05A5A0A8AF0FA8F71C2C2B /* [CP] Embed Pods Frameworks */,
+ D9E654BBB4893905628A201A /* [CP] Embed Pods Frameworks */,
);
buildRules = (
);
@@ -226,7 +226,7 @@
shellPath = /bin/sh;
shellScript = "/bin/sh \"$FLUTTER_ROOT/packages/flutter_tools/bin/xcode_backend.sh\" build";
};
- CE2C3E978245C5FF80E431AC /* [CP] Check Pods Manifest.lock */ = {
+ C54B0935BA386F7769969821 /* [CP] Check Pods Manifest.lock */ = {
isa = PBXShellScriptBuildPhase;
buildActionMask = 2147483647;
files = (
@@ -248,7 +248,7 @@
shellScript = "diff \"${PODS_PODFILE_DIR_PATH}/Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n# This output is used by Xcode 'outputs' to avoid re-running this script phase.\necho \"SUCCESS\" > \"${SCRIPT_OUTPUT_FILE_0}\"\n";
showEnvVarsInLog = 0;
};
- ED05A5A0A8AF0FA8F71C2C2B /* [CP] Embed Pods Frameworks */ = {
+ D9E654BBB4893905628A201A /* [CP] Embed Pods Frameworks */ = {
isa = PBXShellScriptBuildPhase;
buildActionMask = 2147483647;
files = (
@@ -363,7 +363,7 @@
"$(inherited)",
"@executable_path/Frameworks",
);
- PRODUCT_BUNDLE_IDENTIFIER = fr.pointcheval.nativeCryptoIosExample;
+ PRODUCT_BUNDLE_IDENTIFIER = fr.pointcheval.nativeCryptoExample;
PRODUCT_NAME = "$(TARGET_NAME)";
SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h";
SWIFT_VERSION = 5.0;
@@ -492,7 +492,7 @@
"$(inherited)",
"@executable_path/Frameworks",
);
- PRODUCT_BUNDLE_IDENTIFIER = fr.pointcheval.nativeCryptoIosExample;
+ PRODUCT_BUNDLE_IDENTIFIER = fr.pointcheval.nativeCryptoExample;
PRODUCT_NAME = "$(TARGET_NAME)";
SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h";
SWIFT_OPTIMIZATION_LEVEL = "-Onone";
@@ -515,7 +515,7 @@
"$(inherited)",
"@executable_path/Frameworks",
);
- PRODUCT_BUNDLE_IDENTIFIER = fr.pointcheval.nativeCryptoIosExample;
+ PRODUCT_BUNDLE_IDENTIFIER = fr.pointcheval.nativeCryptoExample;
PRODUCT_NAME = "$(TARGET_NAME)";
SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h";
SWIFT_VERSION = 5.0;
diff --git a/native_crypto/example/ios/Runner.xcodeproj/project.xcworkspace/contents.xcworkspacedata b/packages/native_crypto/example/ios/Runner.xcodeproj/project.xcworkspace/contents.xcworkspacedata
similarity index 100%
rename from native_crypto/example/ios/Runner.xcodeproj/project.xcworkspace/contents.xcworkspacedata
rename to packages/native_crypto/example/ios/Runner.xcodeproj/project.xcworkspace/contents.xcworkspacedata
diff --git a/native_crypto/example/ios/Runner.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist b/packages/native_crypto/example/ios/Runner.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist
similarity index 100%
rename from native_crypto/example/ios/Runner.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist
rename to packages/native_crypto/example/ios/Runner.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist
diff --git a/native_crypto/example/ios/Runner.xcodeproj/project.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings b/packages/native_crypto/example/ios/Runner.xcodeproj/project.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings
similarity index 100%
rename from native_crypto/example/ios/Runner.xcodeproj/project.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings
rename to packages/native_crypto/example/ios/Runner.xcodeproj/project.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings
diff --git a/native_crypto/example/ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme b/packages/native_crypto/example/ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme
similarity index 100%
rename from native_crypto/example/ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme
rename to packages/native_crypto/example/ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme
diff --git a/native_crypto_ios/example/ios/Runner.xcworkspace/contents.xcworkspacedata b/packages/native_crypto/example/ios/Runner.xcworkspace/contents.xcworkspacedata
similarity index 100%
rename from native_crypto_ios/example/ios/Runner.xcworkspace/contents.xcworkspacedata
rename to packages/native_crypto/example/ios/Runner.xcworkspace/contents.xcworkspacedata
diff --git a/native_crypto/example/ios/Runner.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist b/packages/native_crypto/example/ios/Runner.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist
similarity index 100%
rename from native_crypto/example/ios/Runner.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist
rename to packages/native_crypto/example/ios/Runner.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist
diff --git a/native_crypto/example/ios/Runner.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings b/packages/native_crypto/example/ios/Runner.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings
similarity index 100%
rename from native_crypto/example/ios/Runner.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings
rename to packages/native_crypto/example/ios/Runner.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings
diff --git a/native_crypto/example/ios/Runner/AppDelegate.swift b/packages/native_crypto/example/ios/Runner/AppDelegate.swift
similarity index 100%
rename from native_crypto/example/ios/Runner/AppDelegate.swift
rename to packages/native_crypto/example/ios/Runner/AppDelegate.swift
diff --git a/native_crypto/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Contents.json b/packages/native_crypto/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Contents.json
similarity index 100%
rename from native_crypto/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Contents.json
rename to packages/native_crypto/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Contents.json
diff --git a/native_crypto/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-1024x1024@1x.png b/packages/native_crypto/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-1024x1024@1x.png
similarity index 100%
rename from native_crypto/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-1024x1024@1x.png
rename to packages/native_crypto/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-1024x1024@1x.png
diff --git a/native_crypto/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@1x.png b/packages/native_crypto/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@1x.png
similarity index 100%
rename from native_crypto/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@1x.png
rename to packages/native_crypto/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@1x.png
diff --git a/native_crypto/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@2x.png b/packages/native_crypto/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@2x.png
similarity index 100%
rename from native_crypto/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@2x.png
rename to packages/native_crypto/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@2x.png
diff --git a/native_crypto/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@3x.png b/packages/native_crypto/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@3x.png
similarity index 100%
rename from native_crypto/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@3x.png
rename to packages/native_crypto/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@3x.png
diff --git a/native_crypto/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@1x.png b/packages/native_crypto/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@1x.png
similarity index 100%
rename from native_crypto/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@1x.png
rename to packages/native_crypto/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@1x.png
diff --git a/native_crypto/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@2x.png b/packages/native_crypto/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@2x.png
similarity index 100%
rename from native_crypto/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@2x.png
rename to packages/native_crypto/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@2x.png
diff --git a/native_crypto/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@3x.png b/packages/native_crypto/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@3x.png
similarity index 100%
rename from native_crypto/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@3x.png
rename to packages/native_crypto/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@3x.png
diff --git a/native_crypto/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@1x.png b/packages/native_crypto/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@1x.png
similarity index 100%
rename from native_crypto/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@1x.png
rename to packages/native_crypto/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@1x.png
diff --git a/native_crypto/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@2x.png b/packages/native_crypto/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@2x.png
similarity index 100%
rename from native_crypto/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@2x.png
rename to packages/native_crypto/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@2x.png
diff --git a/native_crypto/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@3x.png b/packages/native_crypto/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@3x.png
similarity index 100%
rename from native_crypto/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@3x.png
rename to packages/native_crypto/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@3x.png
diff --git a/native_crypto/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@2x.png b/packages/native_crypto/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@2x.png
similarity index 100%
rename from native_crypto/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@2x.png
rename to packages/native_crypto/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@2x.png
diff --git a/native_crypto/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@3x.png b/packages/native_crypto/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@3x.png
similarity index 100%
rename from native_crypto/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@3x.png
rename to packages/native_crypto/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@3x.png
diff --git a/native_crypto/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@1x.png b/packages/native_crypto/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@1x.png
similarity index 100%
rename from native_crypto/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@1x.png
rename to packages/native_crypto/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@1x.png
diff --git a/native_crypto/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@2x.png b/packages/native_crypto/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@2x.png
similarity index 100%
rename from native_crypto/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@2x.png
rename to packages/native_crypto/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@2x.png
diff --git a/native_crypto/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-83.5x83.5@2x.png b/packages/native_crypto/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-83.5x83.5@2x.png
similarity index 100%
rename from native_crypto/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-83.5x83.5@2x.png
rename to packages/native_crypto/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-83.5x83.5@2x.png
diff --git a/native_crypto/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/Contents.json b/packages/native_crypto/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/Contents.json
similarity index 100%
rename from native_crypto/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/Contents.json
rename to packages/native_crypto/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/Contents.json
diff --git a/native_crypto/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage.png b/packages/native_crypto/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage.png
similarity index 100%
rename from native_crypto/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage.png
rename to packages/native_crypto/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage.png
diff --git a/native_crypto/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@2x.png b/packages/native_crypto/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@2x.png
similarity index 100%
rename from native_crypto/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@2x.png
rename to packages/native_crypto/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@2x.png
diff --git a/native_crypto/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@3x.png b/packages/native_crypto/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@3x.png
similarity index 100%
rename from native_crypto/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@3x.png
rename to packages/native_crypto/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@3x.png
diff --git a/native_crypto/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/README.md b/packages/native_crypto/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/README.md
similarity index 100%
rename from native_crypto/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/README.md
rename to packages/native_crypto/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/README.md
diff --git a/native_crypto/example/ios/Runner/Base.lproj/LaunchScreen.storyboard b/packages/native_crypto/example/ios/Runner/Base.lproj/LaunchScreen.storyboard
similarity index 100%
rename from native_crypto/example/ios/Runner/Base.lproj/LaunchScreen.storyboard
rename to packages/native_crypto/example/ios/Runner/Base.lproj/LaunchScreen.storyboard
diff --git a/native_crypto/example/ios/Runner/Base.lproj/Main.storyboard b/packages/native_crypto/example/ios/Runner/Base.lproj/Main.storyboard
similarity index 100%
rename from native_crypto/example/ios/Runner/Base.lproj/Main.storyboard
rename to packages/native_crypto/example/ios/Runner/Base.lproj/Main.storyboard
diff --git a/native_crypto/example/ios/Runner/Info.plist b/packages/native_crypto/example/ios/Runner/Info.plist
similarity index 96%
rename from native_crypto/example/ios/Runner/Info.plist
rename to packages/native_crypto/example/ios/Runner/Info.plist
index 58d9657..8293c48 100644
--- a/native_crypto/example/ios/Runner/Info.plist
+++ b/packages/native_crypto/example/ios/Runner/Info.plist
@@ -43,5 +43,7 @@
UIViewControllerBasedStatusBarAppearance
+ CADisableMinimumFrameDurationOnPhone
+
diff --git a/native_crypto/example/ios/Runner/Runner-Bridging-Header.h b/packages/native_crypto/example/ios/Runner/Runner-Bridging-Header.h
similarity index 100%
rename from native_crypto/example/ios/Runner/Runner-Bridging-Header.h
rename to packages/native_crypto/example/ios/Runner/Runner-Bridging-Header.h
diff --git a/packages/native_crypto/example/lib/home.dart b/packages/native_crypto/example/lib/home.dart
new file mode 100644
index 0000000..8357b7e
--- /dev/null
+++ b/packages/native_crypto/example/lib/home.dart
@@ -0,0 +1,64 @@
+// Author: Hugo Pointcheval
+// Email: git@pcl.ovh
+// -----
+// File: home.dart
+// Created Date: 28/12/2021 13:48:36
+// Last Modified: 28/12/2021 15:18:03
+// -----
+// Copyright (c) 2021
+
+import 'package:flutter/material.dart';
+import 'package:native_crypto_example/pages/benchmark_page.dart';
+
+import 'pages/cipher_page.dart';
+import 'pages/kdf_page.dart';
+
+class Home extends StatefulWidget {
+ const Home({Key? key}) : super(key: key);
+
+ @override
+ _HomeState createState() => _HomeState();
+}
+
+class _HomeState extends State {
+ int _currentIndex = 0;
+ final List _children = [KdfPage(), CipherPage(), BenchmarkPage()];
+
+ void onTabTapped(int index) {
+ setState(() {
+ _currentIndex = index;
+ });
+ }
+
+ @override
+ Widget build(BuildContext context) {
+ return Scaffold(
+ appBar: AppBar(
+ centerTitle: true,
+ title: const Text('Native Crypto'),
+ ),
+ body: _children[_currentIndex],
+ bottomNavigationBar: BottomNavigationBar(
+ selectedItemColor: Colors.blue,
+ unselectedItemColor: Colors.black,
+ showUnselectedLabels: true,
+ onTap: onTabTapped, // new
+ currentIndex: _currentIndex, // new
+ items: const [
+ BottomNavigationBarItem(
+ icon: Icon(Icons.vpn_key),
+ label: 'Key',
+ ),
+ BottomNavigationBarItem(
+ icon: Icon(Icons.lock),
+ label: 'Encryption',
+ ),
+ BottomNavigationBarItem(
+ icon: Icon(Icons.timer),
+ label: 'Benchmark',
+ ),
+ ],
+ ),
+ );
+ }
+}
diff --git a/packages/native_crypto/example/lib/main.dart b/packages/native_crypto/example/lib/main.dart
new file mode 100644
index 0000000..65b60e0
--- /dev/null
+++ b/packages/native_crypto/example/lib/main.dart
@@ -0,0 +1,25 @@
+// Author: Hugo Pointcheval
+// Email: git@pcl.ovh
+// -----
+// File: main.dart
+// Created Date: 27/12/2021 21:15:12
+// Last Modified: 28/12/2021 13:51:36
+// -----
+// Copyright (c) 2021
+
+import 'package:flutter/material.dart';
+import 'package:flutter_riverpod/flutter_riverpod.dart';
+import 'package:native_crypto_example/home.dart';
+
+void main() {
+ runApp(const ProviderScope(child: MyApp()));
+}
+
+class MyApp extends StatelessWidget {
+ const MyApp({Key? key}) : super(key: key);
+
+ @override
+ Widget build(BuildContext context) {
+ return const MaterialApp(home: Home());
+ }
+}
diff --git a/packages/native_crypto/example/lib/pages/benchmark_page.dart b/packages/native_crypto/example/lib/pages/benchmark_page.dart
new file mode 100644
index 0000000..6396152
--- /dev/null
+++ b/packages/native_crypto/example/lib/pages/benchmark_page.dart
@@ -0,0 +1,189 @@
+// Author: Hugo Pointcheval
+// Email: git@pcl.ovh
+// -----
+// File: benchmark_page.dart
+// Created Date: 28/12/2021 15:12:39
+// Last Modified: 26/05/2022 20:19:28
+// -----
+// Copyright (c) 2021
+
+import 'dart:math';
+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';
+import '../widgets/output.dart';
+
+class BenchmarkPage extends ConsumerWidget {
+ BenchmarkPage({Key? key}) : super(key: key);
+
+ final Output keyContent = Output();
+ final Output benchmarkStatus = Output(large: true);
+
+ Future _benchmark(
+ WidgetRef ref,
+ Cipher cipher, {
+ bool usePc = false,
+ bool encryptionOnly = false,
+ }) async {
+ Session state = ref.read(sessionProvider.state).state;
+ AesGcm pc = AesGcm();
+
+ if (state.secretKey.bytes.isEmpty) {
+ benchmarkStatus
+ .print('No SecretKey!\nGo in Key tab and generate or derive one.');
+ return;
+ }
+
+ List testedSizes = [2, 4, 8, 16, 32, 64, 128, 256];
+ int multiplier = pow(2, 20).toInt(); // MiB
+
+ benchmarkStatus.print("[Benchmark] Sizes: ${testedSizes.join('/')}MiB\n");
+ benchmarkStatus.appendln(
+ "[Benchmark] Engine: " + (usePc ? " PointyCastle" : " NativeCrypto"));
+ benchmarkStatus.appendln("[Benchmark] Test: " +
+ (encryptionOnly ? " Encryption Only" : " Encryption & Decryption"));
+ benchmarkStatus.appendln(
+ '[Benchmark] bytesCountPerChunk: ${Cipher.bytesCountPerChunk} bytes/chunk');
+
+ String csv = encryptionOnly
+ ? "Run;Size (B);Encryption Time (ms)\n"
+ : "Run;Size (B);Encryption Time (ms);Decryption Time (ms)\n";
+
+ int run = 0;
+ var beforeBench = DateTime.now();
+
+ for (int size in testedSizes) {
+ run++;
+ final StringBuffer csvLine = StringBuffer();
+ final dummyBytes = Uint8List(size * multiplier);
+ csvLine.write('$run;${size * multiplier};');
+
+ // Encryption
+ Object encryptedBigFile;
+ var before = DateTime.now();
+ if (usePc) {
+ encryptedBigFile = pc.encrypt(dummyBytes, state.secretKey.bytes);
+ } else {
+ encryptedBigFile = await cipher.encrypt(dummyBytes);
+ }
+ var after = DateTime.now();
+
+ var benchmark =
+ after.millisecondsSinceEpoch - before.millisecondsSinceEpoch;
+ benchmarkStatus
+ .appendln('[Benchmark] ${size}MiB => Encryption took $benchmark ms');
+ csvLine.write('$benchmark');
+
+ if (!encryptionOnly) {
+ // Decryption
+ before = DateTime.now();
+ if (usePc) {
+ pc.decrypt(encryptedBigFile as Uint8List, state.secretKey.bytes);
+ } else {
+ await cipher.decrypt(encryptedBigFile as CipherTextWrapper);
+ }
+ after = DateTime.now();
+ benchmark =
+ after.millisecondsSinceEpoch - before.millisecondsSinceEpoch;
+ benchmarkStatus.appendln(
+ '[Benchmark] ${size}MiB => Decryption took $benchmark ms');
+ csvLine.write(';$benchmark');
+ }
+ csv += csvLine.toString() + '\n';
+ }
+ var afterBench = DateTime.now();
+ var benchmark =
+ afterBench.millisecondsSinceEpoch - beforeBench.millisecondsSinceEpoch;
+ var sum = testedSizes.reduce((a, b) => a + b);
+ benchmarkStatus
+ .appendln('[Benchmark] Finished: ${sum}MiB in $benchmark ms');
+ benchmarkStatus.appendln('[Benchmark] Check the console for csv data');
+ benchmarkStatus.appendln(csv);
+ debugPrint(csv);
+ }
+
+ void _clear() {
+ benchmarkStatus.clear();
+ }
+
+ @override
+ Widget build(BuildContext context, WidgetRef ref) {
+ Session state = ref.read(sessionProvider.state).state;
+ if (state.secretKey.bytes.isEmpty) {
+ keyContent
+ .print('No SecretKey!\nGo in Key tab and generate or derive one.');
+ return SingleChildScrollView(
+ child: Padding(
+ padding: const EdgeInsets.all(8.0),
+ child: Column(
+ children: [
+ const Align(
+ child: Text("Secret Key"),
+ alignment: Alignment.centerLeft,
+ ),
+ keyContent,
+ ],
+ ),
+ ),
+ );
+ }
+ keyContent.print(state.secretKey.bytes.toString());
+
+ AES cipher = AES(state.secretKey);
+
+ return SingleChildScrollView(
+ child: Padding(
+ padding: const EdgeInsets.all(8.0),
+ child: Column(
+ children: [
+ const Align(
+ child: Text("Secret Key"),
+ alignment: Alignment.centerLeft,
+ ),
+ keyContent,
+ Wrap(
+ children: [
+ Button(
+ () => _benchmark(ref, cipher),
+ "NativeCrypto",
+ ),
+ const SizedBox(width: 8),
+ Button(
+ () => _benchmark(ref, cipher, usePc: true),
+ "PointyCastle",
+ ),
+ const SizedBox(width: 8),
+ Button(
+ () => _benchmark(ref, cipher, encryptionOnly: true),
+ "NC Encryption Only",
+ ),
+ const SizedBox(width: 8),
+ Button(
+ () => _benchmark(
+ ref,
+ cipher,
+ usePc: true,
+ encryptionOnly: true,
+ ),
+ "PC Encryption Only",
+ ),
+ const SizedBox(width: 8),
+ Button(
+ _clear,
+ "Clear",
+ ),
+ ],
+ ),
+ benchmarkStatus,
+ ],
+ ),
+ ),
+ );
+ }
+}
diff --git a/packages/native_crypto/example/lib/pages/cipher_page.dart b/packages/native_crypto/example/lib/pages/cipher_page.dart
new file mode 100644
index 0000000..b0843c7
--- /dev/null
+++ b/packages/native_crypto/example/lib/pages/cipher_page.dart
@@ -0,0 +1,157 @@
+// Author: Hugo Pointcheval
+// Email: git@pcl.ovh
+// -----
+// File: cipher_page.dart
+// Created Date: 28/12/2021 13:33:15
+// Last Modified: 27/05/2022 16:42:10
+// -----
+// Copyright (c) 2021
+
+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/native_crypto_ext.dart';
+import 'package:native_crypto_example/widgets/button.dart';
+
+import '../session.dart';
+import '../widgets/output.dart';
+
+// ignore: must_be_immutable
+class CipherPage extends ConsumerWidget {
+ CipherPage({Key? key}) : super(key: key);
+
+ final Output keyContent = Output();
+ final Output encryptionStatus = Output();
+ final Output decryptionStatus = Output();
+
+ final TextEditingController _plainTextController = TextEditingController()
+ ..text = 'PlainText';
+ CipherTextWrapper? cipherText;
+
+ Future _encrypt(WidgetRef ref, Cipher cipher) async {
+ Session state = ref.read(sessionProvider.state).state;
+ final plainText = _plainTextController.text.trim();
+
+ if (state.secretKey.bytes.isEmpty) {
+ encryptionStatus
+ .print('No SecretKey!\nGo in Key tab and generate or derive one.');
+ } else if (plainText.isEmpty) {
+ encryptionStatus.print('Entry is empty');
+ } else {
+ var stringToBytes = plainText.toBytes();
+ cipherText = await cipher.encrypt(stringToBytes);
+ encryptionStatus.print('String successfully encrypted:\n');
+
+ CipherText unwrap = cipherText!.unwrap();
+ encryptionStatus.append(unwrap.base16);
+ }
+ }
+
+ Future _alter() async {
+ if (cipherText == null) {
+ decryptionStatus.print('Encrypt before altering CipherText!');
+ } else {
+ // Add 1 to the first byte
+ Uint8List _altered = cipherText!.unwrap().bytes;
+ _altered[0] += 1;
+ // Recreate cipher text with altered data
+ cipherText = CipherTextWrapper.fromBytes(
+ _altered,
+ ivLength: AESMode.gcm.ivLength,
+ tagLength: AESMode.gcm.tagLength,
+ );
+ encryptionStatus.print('String successfully encrypted:\n');
+
+ CipherText unwrap = cipherText!.unwrap();
+ encryptionStatus.appendln(unwrap.base16);
+ decryptionStatus.print('CipherText altered!\nDecryption will fail.');
+ }
+ }
+
+ void _decrypt(WidgetRef ref, Cipher cipher) async {
+ Session state = ref.read(sessionProvider.state).state;
+
+ if (state.secretKey.bytes.isEmpty) {
+ decryptionStatus
+ .print('No SecretKey!\nGo in Key tab and generate or derive one.');
+ } else if (cipherText == null) {
+ decryptionStatus.print('Encrypt before decrypting!');
+ } else {
+ try {
+ Uint8List plainText = await cipher.decrypt(cipherText!);
+ var bytesToString = plainText.toStr();
+ decryptionStatus
+ .print('String successfully decrypted:\n\n$bytesToString');
+ } on NativeCryptoException catch (e) {
+ decryptionStatus.print(e.message ?? 'Decryption failed!');
+ }
+ }
+ }
+
+ @override
+ Widget build(BuildContext context, WidgetRef ref) {
+ Session state = ref.read(sessionProvider.state).state;
+ if (state.secretKey.bytes.isEmpty) {
+ keyContent
+ .print('No SecretKey!\nGo in Key tab and generate or derive one.');
+ return SingleChildScrollView(
+ child: Padding(
+ padding: const EdgeInsets.all(8.0),
+ child: Column(
+ children: [
+ const Align(
+ child: Text("Secret Key"),
+ alignment: Alignment.centerLeft,
+ ),
+ keyContent,
+ ],
+ ),
+ ),
+ );
+ }
+ keyContent.print(state.secretKey.bytes.toString());
+
+ AES cipher = AES(state.secretKey);
+ return SingleChildScrollView(
+ child: Padding(
+ padding: const EdgeInsets.all(8.0),
+ child: Column(
+ children: [
+ const Align(
+ child: Text("Secret Key"),
+ alignment: Alignment.centerLeft,
+ ),
+ keyContent,
+ TextField(
+ controller: _plainTextController,
+ decoration: const InputDecoration(
+ hintText: 'Plain text',
+ ),
+ ),
+ Button(
+ () => _encrypt(ref, cipher),
+ "Encrypt",
+ ),
+ encryptionStatus,
+ Row(
+ mainAxisAlignment: MainAxisAlignment.spaceEvenly,
+ children: [
+ Button(
+ _alter,
+ "Alter cipher",
+ ),
+ Button(
+ () => _decrypt(ref, cipher),
+ "Decrypt",
+ ),
+ ],
+ ),
+ decryptionStatus,
+ ],
+ ),
+ ),
+ );
+ }
+}
diff --git a/packages/native_crypto/example/lib/pages/kdf_page.dart b/packages/native_crypto/example/lib/pages/kdf_page.dart
new file mode 100644
index 0000000..371d883
--- /dev/null
+++ b/packages/native_crypto/example/lib/pages/kdf_page.dart
@@ -0,0 +1,136 @@
+// Author: Hugo Pointcheval
+// Email: git@pcl.ovh
+// -----
+// File: kdf_page.dart
+// Created Date: 28/12/2021 13:40:34
+// Last Modified: 26/05/2022 21:09:47
+// -----
+// Copyright (c) 2021
+
+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/native_crypto_ext.dart';
+import 'package:native_crypto_example/widgets/button.dart';
+
+import '../session.dart';
+import '../widgets/output.dart';
+
+class KdfPage extends ConsumerWidget {
+ KdfPage({Key? key}) : super(key: key);
+
+ final Output keyContent = Output();
+ final Output keyStatus = Output();
+ final Output pbkdf2Status = Output();
+ final Output hashStatus = Output(large: true);
+
+ final TextEditingController _pwdTextController = TextEditingController()
+ ..text = 'Password';
+ final TextEditingController _messageTextController = TextEditingController()
+ ..text = 'Message';
+
+ Future _generate(WidgetRef ref) async {
+ Session state = ref.read(sessionProvider.state).state;
+ try {
+ SecretKey sk = await SecretKey.fromSecureRandom(256);
+ state.setKey(sk);
+ keyStatus.print(
+ "SecretKey successfully generated.\nLength: ${state.secretKey.bytes.length} bytes");
+ keyContent.print(state.secretKey.bytes.toString());
+ debugPrint("As hex :\n${sk.base16}");
+ } catch (e) {
+ keyStatus.print(e.toString());
+ }
+ }
+
+ Future _pbkdf2(WidgetRef ref) async {
+ Session state = ref.read(sessionProvider.state).state;
+ final password = _pwdTextController.text.trim();
+
+ if (password.isEmpty) {
+ pbkdf2Status.print('Password is empty');
+ } else {
+ Pbkdf2 _pbkdf2 = Pbkdf2(
+ keyBytesCount: 32,
+ iterations: 1000,
+ algorithm: HashAlgorithm.sha512,
+ );
+ SecretKey sk = await _pbkdf2.derive(password: password, salt: 'salt');
+ state.setKey(sk);
+ pbkdf2Status.print('Key successfully derived.');
+ keyContent.print(state.secretKey.bytes.toString());
+ debugPrint("As hex :\n${sk.base16}");
+ }
+ }
+
+ Future _hash(HashAlgorithm hasher) async {
+ final message = _messageTextController.text.trim();
+ if (message.isEmpty) {
+ hashStatus.print('Message is empty');
+ } else {
+ Uint8List hash = await hasher.digest(message.toBytes());
+ hashStatus.print(
+ 'Message successfully hashed with $hasher :${hash.toStr(to: Encoding.base16)}');
+ }
+ }
+
+ @override
+ Widget build(BuildContext context, WidgetRef ref) {
+ return SingleChildScrollView(
+ child: Padding(
+ padding: const EdgeInsets.all(8.0),
+ child: Column(
+ children: [
+ const Align(
+ child: Text("SecretKey"),
+ alignment: Alignment.centerLeft,
+ ),
+ keyContent,
+ Button(
+ () => _generate(ref),
+ "Generate SecretKey",
+ ),
+ keyStatus,
+ TextField(
+ controller: _pwdTextController,
+ decoration: const InputDecoration(
+ hintText: 'Password',
+ ),
+ ),
+ Button(
+ () => _pbkdf2(ref),
+ "Apply PBKDF2",
+ ),
+ pbkdf2Status,
+ TextField(
+ controller: _messageTextController,
+ decoration: const InputDecoration(
+ hintText: 'Message',
+ ),
+ ),
+ Row(
+ mainAxisAlignment: MainAxisAlignment.spaceEvenly,
+ children: [
+ Button(
+ () => _hash(HashAlgorithm.sha256),
+ "SHA256",
+ ),
+ Button(
+ () => _hash(HashAlgorithm.sha384),
+ "SHA384",
+ ),
+ Button(
+ () => _hash(HashAlgorithm.sha512),
+ "SHA512",
+ ),
+ ],
+ ),
+ hashStatus,
+ ],
+ ),
+ ),
+ );
+ }
+}
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..967c384
--- /dev/null
+++ b/packages/native_crypto/example/lib/pointycastle/aes_gcm.dart
@@ -0,0 +1,80 @@
+// Author: Hugo Pointcheval
+// Email: git@pcl.ovh
+// -----
+// File: aes_gcm.dart
+// Created Date: 24/05/2022 16:34:54
+// Last Modified: 27/05/2022 17:36:31
+// -----
+// Copyright (c) 2022
+
+// ignore_for_file: implementation_imports
+
+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/lib/session.dart b/packages/native_crypto/example/lib/session.dart
new file mode 100644
index 0000000..7636866
--- /dev/null
+++ b/packages/native_crypto/example/lib/session.dart
@@ -0,0 +1,26 @@
+// Author: Hugo Pointcheval
+// Email: git@pcl.ovh
+// -----
+// File: session.dart
+// Created Date: 28/12/2021 13:54:29
+// Last Modified: 28/12/2021 13:58:49
+// -----
+// Copyright (c) 2021
+
+import 'dart:typed_data';
+
+import 'package:flutter_riverpod/flutter_riverpod.dart';
+import 'package:native_crypto/native_crypto.dart';
+
+class Session {
+ SecretKey secretKey;
+ Session() : secretKey = SecretKey(Uint8List(0));
+
+ void setKey(SecretKey sk) {
+ secretKey = sk;
+ }
+}
+
+// Providers
+
+final sessionProvider = StateProvider((ref) => Session());
diff --git a/packages/native_crypto/example/lib/widgets/button.dart b/packages/native_crypto/example/lib/widgets/button.dart
new file mode 100644
index 0000000..2244bb4
--- /dev/null
+++ b/packages/native_crypto/example/lib/widgets/button.dart
@@ -0,0 +1,31 @@
+// Author: Hugo Pointcheval
+// Email: git@pcl.ovh
+// -----
+// File: button.dart
+// Created Date: 28/12/2021 13:31:17
+// Last Modified: 28/12/2021 13:31:34
+// -----
+// Copyright (c) 2021
+
+import 'package:flutter/material.dart';
+
+class Button extends StatelessWidget {
+ final void Function() onPressed;
+ final String label;
+
+ const Button(this.onPressed, this.label, {Key? key}) : super(key: key);
+
+ @override
+ Widget build(BuildContext context) {
+ return ElevatedButton(
+ onPressed: onPressed,
+ style: TextButton.styleFrom(
+ primary: Colors.blue,
+ ),
+ child: Text(
+ label,
+ style: const TextStyle(color: Colors.white),
+ ),
+ );
+ }
+}
diff --git a/packages/native_crypto/example/lib/widgets/output.dart b/packages/native_crypto/example/lib/widgets/output.dart
new file mode 100644
index 0000000..1dc9b70
--- /dev/null
+++ b/packages/native_crypto/example/lib/widgets/output.dart
@@ -0,0 +1,61 @@
+// Author: Hugo Pointcheval
+// Email: git@pcl.ovh
+// -----
+// File: output.dart
+// Created Date: 28/12/2021 13:31:39
+// Last Modified: 25/05/2022 16:39:39
+// -----
+// Copyright (c) 2021
+
+import 'package:flutter/material.dart';
+
+// ignore: must_be_immutable
+class Output extends StatelessWidget {
+ late TextEditingController controller;
+ final bool large;
+ final bool editable;
+
+ Output({
+ Key? key,
+ TextEditingController? controller,
+ this.large = false,
+ this.editable = false,
+ }) : super(key: key) {
+ this.controller = controller ?? TextEditingController();
+ }
+
+ void print(String message) {
+ debugPrint(message);
+ controller.text = message;
+ }
+
+ void append(String message) {
+ debugPrint(message);
+ controller.text += message;
+ }
+
+ void appendln(String message) {
+ debugPrint(message);
+ controller.text += message + "\n";
+ }
+
+ void clear() {
+ controller.clear();
+ }
+
+ String read() {
+ return controller.text;
+ }
+
+ @override
+ Widget build(BuildContext context) {
+ return TextField(
+ enableInteractiveSelection: true,
+ readOnly: editable ? false : true,
+ minLines: large ? 3 : 1,
+ maxLines: large ? 500 : 5,
+ decoration: const InputDecoration(border: OutlineInputBorder()),
+ controller: controller,
+ );
+ }
+}
diff --git a/native_crypto/example/pubspec.yaml b/packages/native_crypto/example/pubspec.yaml
similarity index 97%
rename from native_crypto/example/pubspec.yaml
rename to packages/native_crypto/example/pubspec.yaml
index e6e3ec3..7fb09c7 100644
--- a/native_crypto/example/pubspec.yaml
+++ b/packages/native_crypto/example/pubspec.yaml
@@ -29,6 +29,8 @@ dependencies:
# The following adds the Cupertino Icons font to your application.
# 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:
@@ -39,7 +41,7 @@ dev_dependencies:
# activated in the `analysis_options.yaml` file located at the root of your
# package. See that file for information about deactivating specific lint
# rules and activating additional ones.
- flutter_lints: ^1.0.0
+ flutter_lints: ^1.0.4
# For information on the generic Dart part of this file, see the
# following page: https://dart.dev/tools/pub/pubspec
diff --git a/packages/native_crypto/lib/native_crypto.dart b/packages/native_crypto/lib/native_crypto.dart
new file mode 100644
index 0000000..2b294a4
--- /dev/null
+++ b/packages/native_crypto/lib/native_crypto.dart
@@ -0,0 +1,30 @@
+// Author: Hugo Pointcheval
+// Email: git@pcl.ovh
+// -----
+// File: native_crypto.dart
+// Created Date: 16/12/2021 16:28:00
+// Last Modified: 26/05/2022 12:10:42
+// -----
+// Copyright (c) 2021
+
+/// Fast and powerful cryptographic functions
+/// thanks to javax.crypto, CommonCrypto and CryptoKit.
+///
+/// Author: Hugo Pointcheval
+library native_crypto;
+
+export 'package:native_crypto_platform_interface/src/utils/exception.dart';
+
+export 'src/builders/builders.dart';
+export 'src/ciphers/ciphers.dart';
+export 'src/core/core.dart';
+export 'src/interfaces/interfaces.dart';
+export 'src/kdf/kdf.dart';
+export 'src/keys/keys.dart';
+// Utils
+export 'src/utils/cipher_algorithm.dart';
+export 'src/utils/hash_algorithm.dart';
+export 'src/utils/kdf_algorithm.dart';
+
+// ignore: constant_identifier_names
+const String AUTHOR = 'Hugo Pointcheval';
diff --git a/packages/native_crypto/lib/native_crypto_ext.dart b/packages/native_crypto/lib/native_crypto_ext.dart
new file mode 100644
index 0000000..0e9502e
--- /dev/null
+++ b/packages/native_crypto/lib/native_crypto_ext.dart
@@ -0,0 +1,11 @@
+// Author: Hugo Pointcheval
+// Email: git@pcl.ovh
+// -----
+// File: native_crypto_ext.dart
+// Created Date: 26/05/2022 19:36:54
+// Last Modified: 26/05/2022 19:38:44
+// -----
+// Copyright (c) 2022
+
+export 'src/utils/encoding.dart';
+export 'src/utils/extensions.dart';
diff --git a/packages/native_crypto/lib/src/builders/builders.dart b/packages/native_crypto/lib/src/builders/builders.dart
new file mode 100644
index 0000000..d846197
--- /dev/null
+++ b/packages/native_crypto/lib/src/builders/builders.dart
@@ -0,0 +1,10 @@
+// Author: Hugo Pointcheval
+// Email: git@pcl.ovh
+// -----
+// File: builders.dart
+// Created Date: 23/05/2022 22:56:03
+// Last Modified: 26/05/2022 19:22:19
+// -----
+// Copyright (c) 2022
+
+export 'decryption_builder.dart';
diff --git a/packages/native_crypto/lib/src/builders/decryption_builder.dart b/packages/native_crypto/lib/src/builders/decryption_builder.dart
new file mode 100644
index 0000000..998fdcf
--- /dev/null
+++ b/packages/native_crypto/lib/src/builders/decryption_builder.dart
@@ -0,0 +1,46 @@
+// Author: Hugo Pointcheval
+// Email: git@pcl.ovh
+// -----
+// File: decryption_builder.dart
+// Created Date: 26/05/2022 19:07:52
+// Last Modified: 26/05/2022 19:21:00
+// -----
+// Copyright (c) 2022
+
+import 'dart:typed_data';
+
+import 'package:flutter/material.dart';
+import 'package:native_crypto/src/core/cipher_text_wrapper.dart';
+import 'package:native_crypto/src/interfaces/cipher.dart';
+
+class DecryptionBuilder extends StatelessWidget {
+ final Cipher cipher;
+ final CipherTextWrapper data;
+ final Widget Function(BuildContext context) onLoading;
+ final Widget Function(BuildContext context, Object error) onError;
+ final Widget Function(BuildContext context, Uint8List plainText) onSuccess;
+
+ const DecryptionBuilder({
+ super.key,
+ required this.cipher,
+ required this.data,
+ required this.onLoading,
+ required this.onError,
+ required this.onSuccess,
+ });
+
+ @override
+ Widget build(BuildContext context) {
+ return FutureBuilder(
+ future: cipher.decrypt(data),
+ builder: (context, snapshot) {
+ if (snapshot.hasData) {
+ return onSuccess(context, snapshot.data!);
+ } else if (snapshot.hasError) {
+ return onError(context, snapshot.error!);
+ }
+ return onLoading(context);
+ },
+ );
+ }
+}
diff --git a/packages/native_crypto/lib/src/ciphers/aes/aes.dart b/packages/native_crypto/lib/src/ciphers/aes/aes.dart
new file mode 100644
index 0000000..b1113fc
--- /dev/null
+++ b/packages/native_crypto/lib/src/ciphers/aes/aes.dart
@@ -0,0 +1,181 @@
+// Author: Hugo Pointcheval
+// Email: git@pcl.ovh
+// -----
+// File: aes.dart
+// Created Date: 16/12/2021 16:28:00
+// Last Modified: 27/05/2022 12:13:28
+// -----
+// Copyright (c) 2022
+
+import 'dart:typed_data';
+
+import 'package:native_crypto/src/ciphers/aes/aes_key_size.dart';
+import 'package:native_crypto/src/ciphers/aes/aes_mode.dart';
+import 'package:native_crypto/src/ciphers/aes/aes_padding.dart';
+import 'package:native_crypto/src/core/cipher_text.dart';
+import 'package:native_crypto/src/core/cipher_text_wrapper.dart';
+import 'package:native_crypto/src/interfaces/cipher.dart';
+import 'package:native_crypto/src/keys/secret_key.dart';
+import 'package:native_crypto/src/platform.dart';
+import 'package:native_crypto/src/utils/cipher_algorithm.dart';
+import 'package:native_crypto/src/utils/extensions.dart';
+import 'package:native_crypto_platform_interface/native_crypto_platform_interface.dart';
+
+export 'aes_key_size.dart';
+export 'aes_mode.dart';
+export 'aes_padding.dart';
+
+/// An AES cipher.
+///
+/// [AES] is a [Cipher] that can be used to encrypt or decrypt data.
+class AES implements Cipher {
+ final SecretKey _key;
+ final AESMode mode;
+ final AESPadding padding;
+
+ @override
+ CipherAlgorithm get algorithm => CipherAlgorithm.aes;
+
+ AES(SecretKey key, [this.mode = AESMode.gcm, this.padding = AESPadding.none])
+ : _key = key {
+ if (!AESKeySize.supportedSizes.contains(key.bitLength)) {
+ throw NativeCryptoException(
+ message: 'Invalid key size! '
+ 'Expected: ${AESKeySize.supportedSizes.join(', ')} bits',
+ code: NativeCryptoExceptionCode.invalid_key_length.code,
+ );
+ }
+
+ if (!mode.supportedPaddings.contains(padding)) {
+ throw NativeCryptoException(
+ message: 'Invalid padding! '
+ 'Expected: ${mode.supportedPaddings.join(', ')}',
+ code: NativeCryptoExceptionCode.invalid_padding.code,
+ );
+ }
+ }
+
+ Future _decrypt(
+ CipherText cipherText, {
+ int chunkCount = 0,
+ }) async {
+ Uint8List? decrypted;
+
+ try {
+ decrypted = await platform.decrypt(
+ cipherText.bytes,
+ _key.bytes,
+ algorithm.name,
+ );
+ } catch (e, s) {
+ throw NativeCryptoException(
+ message: '$e',
+ code: NativeCryptoExceptionCode.platform_throws.code,
+ stackTrace: s,
+ );
+ }
+
+ if (decrypted.isNull) {
+ throw NativeCryptoException(
+ message: 'Platform returned null when decrypting chunk #$chunkCount',
+ code: NativeCryptoExceptionCode.platform_returned_null.code,
+ );
+ } else if (decrypted!.isEmpty) {
+ throw NativeCryptoException(
+ message: 'Platform returned no data when decrypting chunk #$chunkCount',
+ code: NativeCryptoExceptionCode.platform_returned_empty_data.code,
+ );
+ } else {
+ return decrypted;
+ }
+ }
+
+ Future _encrypt(Uint8List data, {int chunkCount = 0}) async {
+ Uint8List? encrypted;
+
+ try {
+ encrypted = await platform.encrypt(
+ data,
+ _key.bytes,
+ algorithm.name,
+ );
+ } catch (e, s) {
+ throw NativeCryptoException(
+ message: '$e on chunk #$chunkCount',
+ code: NativeCryptoExceptionCode.platform_throws.code,
+ stackTrace: s,
+ );
+ }
+
+ if (encrypted.isNull) {
+ throw NativeCryptoException(
+ message: 'Platform returned null when encrypting chunk #$chunkCount',
+ code: NativeCryptoExceptionCode.platform_returned_null.code,
+ );
+ } else if (encrypted!.isEmpty) {
+ throw NativeCryptoException(
+ message: 'Platform returned no data when encrypting chunk #$chunkCount',
+ code: NativeCryptoExceptionCode.platform_returned_empty_data.code,
+ );
+ } else {
+ try {
+ return CipherText.fromBytes(
+ encrypted,
+ ivLength: 12,
+ messageLength: encrypted.length - 28,
+ tagLength: 16,
+ cipherAlgorithm: CipherAlgorithm.aes,
+ );
+ } on NativeCryptoException catch (e, s) {
+ throw NativeCryptoException(
+ message: '${e.message} on chunk #$chunkCount',
+ code: e.code,
+ stackTrace: s,
+ );
+ }
+ }
+ }
+
+ @override
+ Future decrypt(CipherTextWrapper cipherText) async {
+ final BytesBuilder decryptedData = BytesBuilder(copy: false);
+
+ if (cipherText.isList) {
+ int chunkCount = 0;
+ for (final CipherText chunk in cipherText.list) {
+ decryptedData.add(await _decrypt(chunk, chunkCount: chunkCount++));
+ }
+ } else {
+ decryptedData.add(await _decrypt(cipherText.single));
+ }
+
+ return decryptedData.toBytes();
+ }
+
+ @override
+ Future encrypt(Uint8List data) async {
+ if (data.isEmpty) {
+ return CipherTextWrapper.empty();
+ }
+ CipherTextWrapper cipherTextWrapper;
+ Uint8List dataToEncrypt;
+ final int chunkNb = (data.length / Cipher.bytesCountPerChunk).ceil();
+
+ if (chunkNb > 1) {
+ cipherTextWrapper = CipherTextWrapper.empty();
+ for (var i = 0; i < chunkNb; i++) {
+ dataToEncrypt = i < (chunkNb - 1)
+ ? data.sublist(
+ i * Cipher.bytesCountPerChunk,
+ (i + 1) * Cipher.bytesCountPerChunk,
+ )
+ : data.sublist(i * Cipher.bytesCountPerChunk);
+ cipherTextWrapper.add(await _encrypt(dataToEncrypt, chunkCount: i));
+ }
+ } else {
+ cipherTextWrapper = CipherTextWrapper.single(await _encrypt(data));
+ }
+
+ return cipherTextWrapper;
+ }
+}
diff --git a/packages/native_crypto/lib/src/ciphers/aes/aes_key_size.dart b/packages/native_crypto/lib/src/ciphers/aes/aes_key_size.dart
new file mode 100644
index 0000000..befa22f
--- /dev/null
+++ b/packages/native_crypto/lib/src/ciphers/aes/aes_key_size.dart
@@ -0,0 +1,26 @@
+// Author: Hugo Pointcheval
+// Email: git@pcl.ovh
+// -----
+// File: aes_key_size.dart
+// Created Date: 23/05/2022 22:10:07
+// Last Modified: 26/05/2022 18:45:01
+// -----
+// Copyright (c) 2022
+
+/// Defines all available key sizes.
+enum AESKeySize {
+ bits128(128),
+ bits192(192),
+ bits256(256);
+
+ /// Returns the number of bits supported by an [AESKeySize].
+ static final List supportedSizes = [128, 192, 256];
+
+ /// Returns the number of bits in this [AESKeySize].
+ final int bits;
+
+ /// Returns the number of bytes in this [AESKeySize].
+ int get bytes => bits ~/ 8;
+
+ const AESKeySize(this.bits);
+}
diff --git a/packages/native_crypto/lib/src/ciphers/aes/aes_mode.dart b/packages/native_crypto/lib/src/ciphers/aes/aes_mode.dart
new file mode 100644
index 0000000..4bbc7c4
--- /dev/null
+++ b/packages/native_crypto/lib/src/ciphers/aes/aes_mode.dart
@@ -0,0 +1,30 @@
+// Author: Hugo Pointcheval
+// Email: git@pcl.ovh
+// -----
+// File: aes_mode.dart
+// Created Date: 23/05/2022 22:09:16
+// Last Modified: 26/05/2022 21:03:26
+// -----
+// Copyright (c) 2022
+
+import 'package:native_crypto/src/ciphers/aes/aes_padding.dart';
+
+/// Defines the AES modes of operation.
+enum AESMode {
+ gcm([AESPadding.none], 12, 16);
+
+ /// Returns the list of supported [AESPadding] for this [AESMode].
+ final List supportedPaddings;
+
+ /// Returns the default IV length for this [AESMode].
+ final int ivLength;
+
+ /// Returns the default tag length for this [AESMode].
+ final int tagLength;
+
+ const AESMode(
+ this.supportedPaddings, [
+ this.ivLength = 16,
+ this.tagLength = 0,
+ ]);
+}
diff --git a/packages/native_crypto/lib/src/ciphers/aes/aes_padding.dart b/packages/native_crypto/lib/src/ciphers/aes/aes_padding.dart
new file mode 100644
index 0000000..343ae03
--- /dev/null
+++ b/packages/native_crypto/lib/src/ciphers/aes/aes_padding.dart
@@ -0,0 +1,11 @@
+// Author: Hugo Pointcheval
+// Email: git@pcl.ovh
+// -----
+// File: aes_padding.dart
+// Created Date: 23/05/2022 22:10:17
+// Last Modified: 25/05/2022 09:23:49
+// -----
+// Copyright (c) 2022
+
+/// Represents different paddings.
+enum AESPadding { none }
diff --git a/packages/native_crypto/lib/src/ciphers/ciphers.dart b/packages/native_crypto/lib/src/ciphers/ciphers.dart
new file mode 100644
index 0000000..edae6a4
--- /dev/null
+++ b/packages/native_crypto/lib/src/ciphers/ciphers.dart
@@ -0,0 +1,10 @@
+// Author: Hugo Pointcheval
+// Email: git@pcl.ovh
+// -----
+// File: ciphers.dart
+// Created Date: 23/05/2022 22:56:30
+// Last Modified: 23/05/2022 22:56:47
+// -----
+// Copyright (c) 2022
+
+export 'aes/aes.dart';
diff --git a/packages/native_crypto/lib/src/core/cipher_text.dart b/packages/native_crypto/lib/src/core/cipher_text.dart
new file mode 100644
index 0000000..6accd59
--- /dev/null
+++ b/packages/native_crypto/lib/src/core/cipher_text.dart
@@ -0,0 +1,117 @@
+// Author: Hugo Pointcheval
+// Email: git@pcl.ovh
+// -----
+// File: cipher_text.dart
+// Created Date: 16/12/2021 16:59:53
+// Last Modified: 27/05/2022 12:09:47
+// -----
+// Copyright (c) 2021
+
+import 'dart:typed_data';
+
+import 'package:native_crypto/src/core/cipher_text_wrapper.dart';
+import 'package:native_crypto/src/interfaces/byte_array.dart';
+import 'package:native_crypto/src/interfaces/cipher.dart';
+import 'package:native_crypto/src/utils/cipher_algorithm.dart';
+import 'package:native_crypto/src/utils/extensions.dart';
+import 'package:native_crypto_platform_interface/native_crypto_platform_interface.dart';
+
+/// Represents a cipher text in NativeCrypto.
+///
+/// [CipherText] is a [ByteArray] that can be used to store encrypted data.
+/// It is represented like:
+/// ```txt
+/// [IV + MESSAGE + TAG]
+/// ```
+/// where:
+/// - IV's length is [CipherText.ivLength] bytes.
+/// - MESSAGE's length is [CipherText.messageLength] bytes.
+/// - TAG's length is [CipherText.tagLength] bytes.
+///
+/// Check [CipherTextWrapper] for more information.
+class CipherText extends ByteArray {
+ final int _ivLength;
+ final int _messageLength;
+ final int _tagLength;
+
+ final CipherAlgorithm? _cipherAlgorithm;
+
+ const CipherText._(
+ this._ivLength,
+ this._messageLength,
+ this._tagLength,
+ this._cipherAlgorithm,
+ super.bytes,
+ );
+
+ factory CipherText.fromBytes(
+ Uint8List bytes, {
+ required int ivLength,
+ required int tagLength,
+ int? messageLength,
+ CipherAlgorithm? cipherAlgorithm,
+ }) {
+ messageLength ??= bytes.length - ivLength - tagLength;
+
+ if (ivLength.isNegative ||
+ messageLength.isNegative ||
+ tagLength.isNegative) {
+ throw NativeCryptoException(
+ message: 'Invalid length! Must be positive.',
+ code: NativeCryptoExceptionCode.invalid_argument.code,
+ );
+ }
+
+ if (bytes.isEmpty) {
+ throw NativeCryptoException(
+ message: 'Passed data is empty!',
+ code: NativeCryptoExceptionCode.invalid_argument.code,
+ );
+ }
+
+ if (bytes.length != ivLength + messageLength + tagLength) {
+ throw NativeCryptoException(
+ message: 'Invalid cipher text length! '
+ 'Expected: ${ivLength + messageLength + tagLength} bytes '
+ 'got: ${bytes.length} bytes.',
+ code: NativeCryptoExceptionCode.invalid_argument.code,
+ );
+ }
+
+ if (messageLength > Cipher.bytesCountPerChunk) {
+ throw NativeCryptoException(
+ message: 'Cipher text is too big! Consider using chunks.',
+ code: NativeCryptoExceptionCode.invalid_argument.code,
+ );
+ }
+
+ return CipherText._(
+ ivLength,
+ messageLength,
+ tagLength,
+ cipherAlgorithm,
+ bytes,
+ );
+ }
+
+ /// Gets the [CipherAlgorithm] used to encrypt the [CipherText].
+ CipherAlgorithm get cipherAlgorithm {
+ if (_cipherAlgorithm.isNotNull) {
+ return _cipherAlgorithm!;
+ } else {
+ throw NativeCryptoException(
+ message: 'Cipher algorithm is not specified',
+ code: NativeCryptoExceptionCode.invalid_cipher.code,
+ );
+ }
+ }
+
+ /// Gets the length of the [CipherText]'s IV.
+ int get ivLength => _ivLength;
+
+ /// Gets the length of the [CipherText]'s Message.
+ int get messageLength => _messageLength;
+
+ /// Gets the length of the [CipherText]'s Tag.
+ int get tagLength => _tagLength;
+}
diff --git a/packages/native_crypto/lib/src/core/cipher_text_wrapper.dart b/packages/native_crypto/lib/src/core/cipher_text_wrapper.dart
new file mode 100644
index 0000000..75a9dae
--- /dev/null
+++ b/packages/native_crypto/lib/src/core/cipher_text_wrapper.dart
@@ -0,0 +1,191 @@
+// Author: Hugo Pointcheval
+// Email: git@pcl.ovh
+// -----
+// File: cipher_text_wrapper.dart
+// Created Date: 26/05/2022 14:27:32
+// Last Modified: 27/05/2022 13:43:29
+// -----
+// Copyright (c) 2022
+
+import 'dart:typed_data';
+
+import 'package:native_crypto/native_crypto.dart';
+import 'package:native_crypto/src/utils/extensions.dart';
+
+/// Wrapper for [CipherText]
+///
+/// Typically, this object is the result of an encryption operation.
+/// For decryption you have to build this before using it.
+class CipherTextWrapper {
+ final CipherText? _single;
+ final List? _list;
+
+ CipherTextWrapper._(this._single, this._list);
+
+ /// Creates a [CipherTextWrapper] from a [CipherText].
+ factory CipherTextWrapper.single(CipherText cipherText) =>
+ CipherTextWrapper._(cipherText, null);
+
+ /// Creates a [CipherTextWrapper] from a [List] of [CipherText].
+ factory CipherTextWrapper.list(List cipherTexts) =>
+ CipherTextWrapper._(null, cipherTexts);
+
+ /// Creates an empty [List] in a [CipherTextWrapper].
+ ///
+ /// This is useful when you want to create a [CipherTextWrapper] then
+ /// fill it with data.
+ factory CipherTextWrapper.empty() => CipherTextWrapper._(null, []);
+
+ /// Creates a [CipherTextWrapper] from a [Uint8List].
+ ///
+ /// This is a convenience method to create a [CipherTextWrapper]
+ /// from a [Uint8List]. It tries to detect if the [Uint8List] is a
+ /// single [CipherText] or a list of [CipherText].
+ ///
+ /// You can customize the chunk size by passing a [chunkSize] parameter.
+ /// The default chunk size is [Cipher.bytesCountPerChunk].
+ ///
+ /// Throw an [NativeCryptoExceptionCode] with
+ /// [NativeCryptoExceptionCode.invalid_argument] if the [Uint8List] is
+ /// not a valid [CipherText] or a [List] of [CipherText].
+ factory CipherTextWrapper.fromBytes(
+ Uint8List bytes, {
+ required int ivLength,
+ required int tagLength,
+ CipherAlgorithm? cipherAlgorithm,
+ int? chunkSize,
+ }) {
+ chunkSize ??= Cipher.bytesCountPerChunk;
+ Cipher.bytesCountPerChunk = chunkSize;
+
+ final int messageLength = bytes.length - ivLength - tagLength;
+
+ if (messageLength <= chunkSize) {
+ return CipherTextWrapper.single(
+ CipherText.fromBytes(
+ bytes,
+ ivLength: ivLength,
+ tagLength: tagLength,
+ cipherAlgorithm: cipherAlgorithm,
+ ),
+ );
+ } else {
+ final cipherTexts = [];
+ for (var i = 0; i < bytes.length; i += chunkSize + ivLength + tagLength) {
+ final chunk = bytes.trySublist(i, i + chunkSize + ivLength + tagLength);
+
+ try {
+ cipherTexts.add(
+ CipherText.fromBytes(
+ chunk,
+ ivLength: ivLength,
+ tagLength: tagLength,
+ cipherAlgorithm: cipherAlgorithm,
+ ),
+ );
+ } on NativeCryptoException catch (e, s) {
+ throw NativeCryptoException(
+ message: '${e.message} on chunk #$i',
+ code: e.code,
+ stackTrace: s,
+ );
+ }
+ }
+ return CipherTextWrapper.list(cipherTexts);
+ }
+ }
+
+ /// Checks if the [CipherText] is a single [CipherText].
+ bool get isSingle => _single.isNotNull;
+
+ /// Checks if the [CipherText] is a [List] of [CipherText].
+ bool get isList => _list.isNotNull;
+
+ /// Gets the [CipherText] if it's a single one.
+ ///
+ /// Throws [NativeCryptoException] with
+ /// [NativeCryptoExceptionCode.invalid_data] if it's not a single one.
+ CipherText get single {
+ if (isSingle) {
+ return _single!;
+ } else {
+ throw NativeCryptoException(
+ message: 'CipherTextWrapper is not single',
+ code: NativeCryptoExceptionCode.invalid_data.code,
+ );
+ }
+ }
+
+ /// Gets the [List] of [CipherText] if it's a list.
+ ///
+ /// Throws [NativeCryptoException] with
+ /// [NativeCryptoExceptionCode.invalid_data] if it's not a list.
+ List get list {
+ if (isList) {
+ return _list!;
+ } else {
+ throw NativeCryptoException(
+ message: 'CipherTextWrapper is not list',
+ code: NativeCryptoExceptionCode.invalid_data.code,
+ );
+ }
+ }
+
+ /// Gets the raw [Uint8List] of the [CipherText] or [List] of [CipherText].
+ Uint8List get bytes {
+ if (isSingle) {
+ return single.bytes;
+ } else {
+ return list.map((cipherText) => cipherText.bytes).toList().combine();
+ }
+ }
+
+ /// Gets the number of parts of the [CipherText] or [List] of [CipherText].
+ ///
+ /// Check [Cipher.bytesCountPerChunk] for more information.
+ int get chunkCount {
+ _single.isNull;
+ if (_single.isNotNull) {
+ return 1;
+ } else {
+ return _list?.length ?? 0;
+ }
+ }
+
+ /// Gets the [CipherText] or the [List] of [CipherText].
+ ///
+ /// Throws [NativeCryptoException] with
+ /// [NativeCryptoExceptionCode.invalid_data] if it's not a single or a list or
+ /// if [T] is not [CipherText] or [List] of [CipherText].
+ T unwrap() {
+ if (isSingle && T == CipherText) {
+ return single as T;
+ } else if (isList && T == List) {
+ return list as T;
+ } else {
+ final String type =
+ isSingle ? 'CipherText' : (isList ? 'List' : 'unknown');
+ throw NativeCryptoException(
+ message: 'CipherTextWrapper is not a $T but a $type, '
+ 'you should use unwrap<$type>()',
+ code: NativeCryptoExceptionCode.invalid_data.code,
+ );
+ }
+ }
+
+ void add(CipherText cipherText) {
+ if (isSingle) {
+ throw NativeCryptoException(
+ message: 'CipherTextWrapper is already single',
+ code: NativeCryptoExceptionCode.invalid_data.code,
+ );
+ } else if (isList) {
+ _list!.add(cipherText);
+ } else {
+ throw NativeCryptoException(
+ message: 'CipherTextWrapper is not single or list',
+ code: NativeCryptoExceptionCode.invalid_data.code,
+ );
+ }
+ }
+}
diff --git a/packages/native_crypto/lib/src/core/core.dart b/packages/native_crypto/lib/src/core/core.dart
new file mode 100644
index 0000000..32ad783
--- /dev/null
+++ b/packages/native_crypto/lib/src/core/core.dart
@@ -0,0 +1,11 @@
+// Author: Hugo Pointcheval
+// Email: git@pcl.ovh
+// -----
+// File: core.dart
+// Created Date: 23/05/2022 23:05:26
+// Last Modified: 26/05/2022 17:10:25
+// -----
+// Copyright (c) 2022
+
+export 'cipher_text.dart';
+export 'cipher_text_wrapper.dart';
diff --git a/packages/native_crypto/lib/src/interfaces/base_key.dart b/packages/native_crypto/lib/src/interfaces/base_key.dart
new file mode 100644
index 0000000..e8ac27e
--- /dev/null
+++ b/packages/native_crypto/lib/src/interfaces/base_key.dart
@@ -0,0 +1,22 @@
+// Author: Hugo Pointcheval
+// Email: git@pcl.ovh
+// -----
+// File: base_key.dart
+// Created Date: 16/12/2021 16:28:00
+// Last Modified: 26/05/2022 17:40:38
+// -----
+// Copyright (c) 2021
+
+import 'package:native_crypto/src/interfaces/byte_array.dart';
+
+/// Represents a key in NativeCrypto.
+///
+/// [BaseKey] is a [ByteArray] that can be used to store keys.
+///
+/// This interface is implemented by all the key classes.
+abstract class BaseKey extends ByteArray {
+ const BaseKey(super.bytes);
+ BaseKey.fromBase16(super.encoded) : super.fromBase16();
+ BaseKey.fromBase64(super.encoded) : super.fromBase64();
+ BaseKey.fromUtf8(super.input) : super.fromUtf8();
+}
diff --git a/packages/native_crypto/lib/src/interfaces/builder.dart b/packages/native_crypto/lib/src/interfaces/builder.dart
new file mode 100644
index 0000000..a1b39aa
--- /dev/null
+++ b/packages/native_crypto/lib/src/interfaces/builder.dart
@@ -0,0 +1,14 @@
+// Author: Hugo Pointcheval
+// Email: git@pcl.ovh
+// -----
+// File: builder.dart
+// Created Date: 28/12/2021 12:02:34
+// Last Modified: 23/05/2022 22:38:44
+// -----
+// Copyright (c) 2021
+
+// ignore_for_file: one_member_abstracts
+
+abstract class Builder {
+ Future build();
+}
diff --git a/packages/native_crypto/lib/src/interfaces/byte_array.dart b/packages/native_crypto/lib/src/interfaces/byte_array.dart
new file mode 100644
index 0000000..7cdef3a
--- /dev/null
+++ b/packages/native_crypto/lib/src/interfaces/byte_array.dart
@@ -0,0 +1,92 @@
+// Author: Hugo Pointcheval
+// Email: git@pcl.ovh
+// -----
+// File: byte_array.dart
+// Created Date: 16/12/2021 17:54:16
+// Last Modified: 26/05/2022 17:13:27
+// -----
+// Copyright (c) 2021
+
+import 'dart:typed_data';
+
+import 'package:flutter/foundation.dart';
+import 'package:native_crypto/src/utils/encoding.dart';
+import 'package:native_crypto/src/utils/extensions.dart';
+
+/// Represents a byte array.
+///
+/// [ByteArray] wraps a [Uint8List] and provides some useful conversion methods.
+@immutable
+abstract class ByteArray {
+ final Uint8List _bytes;
+
+ /// Creates a [ByteArray] from a [Uint8List].
+ const ByteArray(this._bytes);
+
+ /// Creates a [ByteArray] object from a hexdecimal string.
+ ByteArray.fromBase16(String encoded)
+ : _bytes = encoded.toBytes(from: Encoding.base16);
+
+ /// Creates a [ByteArray] object from a Base64 string.
+ ByteArray.fromBase64(String encoded)
+ : _bytes = encoded.toBytes(from: Encoding.base64);
+
+ /// Creates a [ByteArray] object from an UTF-8 string.
+ ByteArray.fromUtf8(String encoded)
+ : _bytes = encoded.toBytes(from: Encoding.utf8);
+
+ /// Creates a [ByteArray] object from an UTF-16 string.
+ ByteArray.fromUtf16(String encoded) : _bytes = encoded.toBytes();
+
+ /// Creates an empty [ByteArray] object from a length.
+ ByteArray.fromLength(int length) : _bytes = Uint8List(length);
+
+ /// Creates a [ByteArray] object from a [List] of [int].
+ ByteArray.fromList(List list) : _bytes = list.toTypedList();
+
+ /// Gets the [ByteArray] bytes.
+ Uint8List get bytes => _bytes;
+
+ /// Gets the [ByteArray] bytes as a Hexadecimal representation.
+ String get base16 => _bytes.toStr(to: Encoding.base16);
+
+ /// Gets the [ByteArray] bytes as a Base64 representation.
+ String get base64 => _bytes.toStr(to: Encoding.base64);
+
+ /// Gets the [ByteArray] bytes as an UTF-8 representation.
+ String get utf8 => _bytes.toStr(to: Encoding.utf8);
+
+ /// Gets the [ByteArray] bytes as an UTF-16 representation.
+ String get utf16 => _bytes.toStr();
+
+ /// Gets the [ByteArray] length in bytes.
+ int get length => _bytes.length;
+
+ /// Gets the [ByteArray] length in bits.
+ int get bitLength => _bytes.length * 8;
+
+ @override
+ bool operator ==(Object other) {
+ if (other is ByteArray) {
+ for (int i = 0; i < _bytes.length; i++) {
+ if (_bytes[i] != other._bytes[i]) {
+ return false;
+ }
+ }
+
+ return true;
+ }
+
+ return false;
+ }
+
+ @override
+ int get hashCode {
+ int hash = 0;
+ for (int i = 0; i < _bytes.length; i++) {
+ hash = _bytes[i] + (hash << 6) + (hash << 16) - hash;
+ }
+
+ return hash;
+ }
+}
diff --git a/packages/native_crypto/lib/src/interfaces/cipher.dart b/packages/native_crypto/lib/src/interfaces/cipher.dart
new file mode 100644
index 0000000..58b0d4a
--- /dev/null
+++ b/packages/native_crypto/lib/src/interfaces/cipher.dart
@@ -0,0 +1,53 @@
+// Author: Hugo Pointcheval
+// Email: git@pcl.ovh
+// -----
+// File: cipher.dart
+// Created Date: 16/12/2021 16:28:00
+// Last Modified: 26/05/2022 21:21:07
+// -----
+// Copyright (c) 2021
+
+import 'dart:typed_data';
+
+import 'package:native_crypto/src/core/cipher_text_wrapper.dart';
+import 'package:native_crypto/src/utils/cipher_algorithm.dart';
+
+/// Represents a cipher in NativeCrypto.
+///
+/// In cryptography, a [Cipher] is an algorithm for performing encryption
+/// or decryption - a series of well-defined steps that can
+/// be followed as a procedure.
+///
+/// This interface is implemented by all the ciphers in NativeCrypto.
+abstract class Cipher {
+ static const int _bytesCountPerChunkDefault = 33554432;
+ static int _bytesCountPerChunk = _bytesCountPerChunkDefault;
+
+ /// Returns the default number of bytes per chunk.
+ static int get defaultBytesCountPerChunk => _bytesCountPerChunkDefault;
+
+ /// Returns the size of a chunk of data
+ /// that can be processed by the [Cipher].
+ static int get bytesCountPerChunk => Cipher._bytesCountPerChunk;
+
+ /// Sets the size of a chunk of data
+ /// that can be processed by the [Cipher].
+ static set bytesCountPerChunk(int bytesCount) {
+ _bytesCountPerChunk = bytesCount;
+ }
+
+ /// Returns the standard algorithm for this [Cipher].
+ CipherAlgorithm get algorithm;
+
+ /// Encrypts the [data].
+ ///
+ /// Takes [Uint8List] data as parameter.
+ /// Returns a [CipherTextWrapper].
+ Future encrypt(Uint8List data);
+
+ /// Decrypts the [cipherText]
+ ///
+ /// Takes [CipherTextWrapper] as parameter.
+ /// And returns plain text data as [Uint8List].
+ Future decrypt(CipherTextWrapper cipherText);
+}
diff --git a/packages/native_crypto/lib/src/interfaces/interfaces.dart b/packages/native_crypto/lib/src/interfaces/interfaces.dart
new file mode 100644
index 0000000..ef47be3
--- /dev/null
+++ b/packages/native_crypto/lib/src/interfaces/interfaces.dart
@@ -0,0 +1,14 @@
+// Author: Hugo Pointcheval
+// Email: git@pcl.ovh
+// -----
+// File: interfaces.dart
+// Created Date: 23/05/2022 23:03:47
+// Last Modified: 26/05/2022 17:41:06
+// -----
+// Copyright (c) 2022
+
+export 'base_key.dart';
+export 'builder.dart';
+export 'byte_array.dart';
+export 'cipher.dart';
+export 'keyderivation.dart';
diff --git a/packages/native_crypto/lib/src/interfaces/keyderivation.dart b/packages/native_crypto/lib/src/interfaces/keyderivation.dart
new file mode 100644
index 0000000..ccdbb4b
--- /dev/null
+++ b/packages/native_crypto/lib/src/interfaces/keyderivation.dart
@@ -0,0 +1,23 @@
+// Author: Hugo Pointcheval
+// Email: git@pcl.ovh
+// -----
+// File: kdf.dart
+// Created Date: 18/12/2021 11:56:43
+// Last Modified: 26/05/2022 18:47:15
+// -----
+// Copyright (c) 2021
+
+import 'package:native_crypto/src/keys/secret_key.dart';
+import 'package:native_crypto/src/utils/kdf_algorithm.dart';
+
+/// Represents a Key Derivation Function (KDF) in NativeCrypto.
+///
+/// [KeyDerivation] function is a function that takes some
+/// parameters and returns a [SecretKey].
+abstract class KeyDerivation {
+ /// Returns the standard algorithm for this key derivation function
+ KdfAlgorithm get algorithm;
+
+ /// Derive a [SecretKey].
+ Future derive();
+}
diff --git a/packages/native_crypto/lib/src/kdf/kdf.dart b/packages/native_crypto/lib/src/kdf/kdf.dart
new file mode 100644
index 0000000..cb7d609
--- /dev/null
+++ b/packages/native_crypto/lib/src/kdf/kdf.dart
@@ -0,0 +1,10 @@
+// Author: Hugo Pointcheval
+// Email: git@pcl.ovh
+// -----
+// File: kdf.dart
+// Created Date: 23/05/2022 22:57:11
+// Last Modified: 23/05/2022 23:04:15
+// -----
+// Copyright (c) 2022
+
+export 'pbkdf2.dart';
diff --git a/packages/native_crypto/lib/src/kdf/pbkdf2.dart b/packages/native_crypto/lib/src/kdf/pbkdf2.dart
new file mode 100644
index 0000000..8ccdadd
--- /dev/null
+++ b/packages/native_crypto/lib/src/kdf/pbkdf2.dart
@@ -0,0 +1,115 @@
+// Author: Hugo Pointcheval
+// Email: git@pcl.ovh
+// -----
+// File: pbkdf2.dart
+// Created Date: 17/12/2021 14:50:42
+// Last Modified: 26/05/2022 23:19:46
+// -----
+// Copyright (c) 2021
+
+import 'dart:typed_data';
+
+import 'package:native_crypto/src/interfaces/keyderivation.dart';
+import 'package:native_crypto/src/keys/secret_key.dart';
+import 'package:native_crypto/src/platform.dart';
+import 'package:native_crypto/src/utils/extensions.dart';
+import 'package:native_crypto/src/utils/hash_algorithm.dart';
+import 'package:native_crypto/src/utils/kdf_algorithm.dart';
+import 'package:native_crypto_platform_interface/native_crypto_platform_interface.dart';
+
+/// Represent a PBKDF2 Key Derivation Function (KDF) in NativeCrypto.
+///
+/// [Pbkdf2] is a function that takes password, salt, iteration count and
+/// derive a [SecretKey] of specified length.
+class Pbkdf2 extends KeyDerivation {
+ final int _keyBytesCount;
+ final int _iterations;
+ final HashAlgorithm _hash;
+
+ @override
+ KdfAlgorithm get algorithm => KdfAlgorithm.pbkdf2;
+
+ Pbkdf2({
+ required int keyBytesCount,
+ required int iterations,
+ HashAlgorithm algorithm = HashAlgorithm.sha256,
+ }) : _keyBytesCount = keyBytesCount,
+ _iterations = iterations,
+ _hash = algorithm {
+ if (keyBytesCount < 0) {
+ throw NativeCryptoException(
+ message: 'keyBytesCount must be positive.',
+ code: NativeCryptoExceptionCode.invalid_argument.code,
+ );
+ }
+
+ if (iterations <= 0) {
+ throw NativeCryptoException(
+ message: 'iterations must be strictly positive.',
+ code: NativeCryptoExceptionCode.invalid_argument.code,
+ );
+ }
+ }
+
+ @override
+ Future derive({String? password, String? salt}) async {
+ Uint8List? derivation;
+
+ if (_keyBytesCount == 0) {
+ return SecretKey(Uint8List(0));
+ }
+ if (password.isNull) {
+ throw NativeCryptoException(
+ message: 'Password cannot be null.',
+ code: NativeCryptoExceptionCode.invalid_argument.code,
+ );
+ }
+
+ if (salt.isNull) {
+ throw NativeCryptoException(
+ message: 'Salt cannot be null.',
+ code: NativeCryptoExceptionCode.invalid_argument.code,
+ );
+ }
+
+ try {
+ derivation = await platform.pbkdf2(
+ password!,
+ salt!,
+ _keyBytesCount,
+ _iterations,
+ _hash.name,
+ );
+ } catch (e, s) {
+ throw NativeCryptoException(
+ message: '$e',
+ code: NativeCryptoExceptionCode.platform_throws.code,
+ stackTrace: s,
+ );
+ }
+
+ if (derivation.isNull) {
+ throw NativeCryptoException(
+ message: 'Failed to derive a key! Platform returned null.',
+ code: NativeCryptoExceptionCode.platform_returned_null.code,
+ );
+ }
+
+ if (derivation!.isEmpty) {
+ throw NativeCryptoException(
+ message: 'Failed to derive a key! Platform returned no data.',
+ code: NativeCryptoExceptionCode.platform_returned_empty_data.code,
+ );
+ }
+
+ if (derivation.length != _keyBytesCount) {
+ throw NativeCryptoException(
+ message: 'Failed to derive a key! Platform returned '
+ '${derivation.length} bytes, but expected $_keyBytesCount bytes.',
+ code: NativeCryptoExceptionCode.platform_returned_invalid_data.code,
+ );
+ }
+
+ return SecretKey(derivation);
+ }
+}
diff --git a/packages/native_crypto/lib/src/keys/keys.dart b/packages/native_crypto/lib/src/keys/keys.dart
new file mode 100644
index 0000000..912bb39
--- /dev/null
+++ b/packages/native_crypto/lib/src/keys/keys.dart
@@ -0,0 +1,10 @@
+// Author: Hugo Pointcheval
+// Email: git@pcl.ovh
+// -----
+// File: keys.dart
+// Created Date: 23/05/2022 23:04:04
+// Last Modified: 23/05/2022 23:04:07
+// -----
+// Copyright (c) 2022
+
+export 'secret_key.dart';
diff --git a/packages/native_crypto/lib/src/keys/secret_key.dart b/packages/native_crypto/lib/src/keys/secret_key.dart
new file mode 100644
index 0000000..e30b87b
--- /dev/null
+++ b/packages/native_crypto/lib/src/keys/secret_key.dart
@@ -0,0 +1,60 @@
+// Author: Hugo Pointcheval
+// Email: git@pcl.ovh
+// -----
+// File: secret_key.dart
+// Created Date: 28/12/2021 13:36:54
+// Last Modified: 26/05/2022 23:13:10
+// -----
+// Copyright (c) 2021
+
+import 'dart:typed_data';
+
+import 'package:native_crypto/src/interfaces/base_key.dart';
+import 'package:native_crypto/src/interfaces/cipher.dart';
+import 'package:native_crypto/src/platform.dart';
+import 'package:native_crypto/src/utils/extensions.dart';
+import 'package:native_crypto_platform_interface/native_crypto_platform_interface.dart';
+
+/// Represents a secret key in NativeCrypto.
+///
+/// [SecretKey] is a [BaseKey] that can be used to store secret keys.
+/// A [SecretKey] is a key that can be used to encrypt or decrypt data with
+/// a symmetric [Cipher].
+class SecretKey extends BaseKey {
+ const SecretKey(super.bytes);
+ SecretKey.fromBase16(super.encoded) : super.fromBase16();
+ SecretKey.fromBase64(super.encoded) : super.fromBase64();
+ SecretKey.fromUtf8(super.input) : super.fromUtf8();
+
+ static Future fromSecureRandom(int bitsCount) async {
+ Uint8List? key;
+ if (bitsCount == 0) {
+ return SecretKey(Uint8List(0));
+ }
+
+ try {
+ key = await platform.generateSecretKey(bitsCount);
+ } catch (e, s) {
+ throw NativeCryptoException(
+ message: '$e',
+ code: NativeCryptoExceptionCode.platform_throws.code,
+ stackTrace: s,
+ );
+ }
+ if (key.isNull) {
+ throw NativeCryptoException(
+ message: 'Failed to generate a secret key! Platform returned null.',
+ code: NativeCryptoExceptionCode.platform_returned_null.code,
+ );
+ }
+
+ if (key!.isEmpty) {
+ throw NativeCryptoException(
+ message: 'Failed to generate a secret key! '
+ 'Platform returned no data.',
+ code: NativeCryptoExceptionCode.platform_returned_empty_data.code,
+ );
+ }
+ return SecretKey(key);
+ }
+}
diff --git a/packages/native_crypto/lib/src/platform.dart b/packages/native_crypto/lib/src/platform.dart
new file mode 100644
index 0000000..5d62b5e
--- /dev/null
+++ b/packages/native_crypto/lib/src/platform.dart
@@ -0,0 +1,12 @@
+// Author: Hugo Pointcheval
+// Email: git@pcl.ovh
+// -----
+// File: platform.dart
+// Created Date: 27/12/2021 22:03:58
+// Last Modified: 25/05/2022 10:09:18
+// -----
+// Copyright (c) 2021
+
+import 'package:native_crypto_platform_interface/native_crypto_platform_interface.dart';
+
+NativeCryptoPlatform platform = NativeCryptoPlatform.instance;
diff --git a/packages/native_crypto/lib/src/utils/cipher_algorithm.dart b/packages/native_crypto/lib/src/utils/cipher_algorithm.dart
new file mode 100644
index 0000000..2ba968c
--- /dev/null
+++ b/packages/native_crypto/lib/src/utils/cipher_algorithm.dart
@@ -0,0 +1,11 @@
+// Author: Hugo Pointcheval
+// Email: git@pcl.ovh
+// -----
+// File: cipher_algorithm.dart
+// Created Date: 23/05/2022 22:07:54
+// Last Modified: 26/05/2022 18:52:32
+// -----
+// Copyright (c) 2022
+
+/// Represents different cipher algorithms
+enum CipherAlgorithm { aes }
diff --git a/packages/native_crypto/lib/src/utils/encoding.dart b/packages/native_crypto/lib/src/utils/encoding.dart
new file mode 100644
index 0000000..b7ddd80
--- /dev/null
+++ b/packages/native_crypto/lib/src/utils/encoding.dart
@@ -0,0 +1,10 @@
+// Author: Hugo Pointcheval
+// Email: git@pcl.ovh
+// -----
+// File: encoding.dart
+// Created Date: 26/05/2022 12:12:34
+// Last Modified: 26/05/2022 12:18:09
+// -----
+// Copyright (c) 2022
+
+enum Encoding { utf8, utf16, base64, base16 }
diff --git a/packages/native_crypto/lib/src/utils/extensions.dart b/packages/native_crypto/lib/src/utils/extensions.dart
new file mode 100644
index 0000000..fc2a799
--- /dev/null
+++ b/packages/native_crypto/lib/src/utils/extensions.dart
@@ -0,0 +1,101 @@
+// Author: Hugo Pointcheval
+// Email: git@pcl.ovh
+// -----
+// File: extensions.dart
+// Created Date: 26/05/2022 12:12:48
+// Last Modified: 27/05/2022 12:26:55
+// -----
+// Copyright (c) 2022
+
+import 'dart:convert';
+import 'dart:developer' as developer;
+import 'dart:typed_data';
+
+import 'package:native_crypto/src/utils/encoding.dart';
+
+extension ObjectX on Object? {
+ /// Returns `true` if the object is `null`.
+ bool get isNull => this == null;
+
+ /// Returns `true` if the object is **not** `null`.
+ bool get isNotNull => this != null;
+
+ /// Prints the object to the console.
+ void log() => developer.log(toString());
+}
+
+extension ListIntX on List {
+ /// Converts a [List] of int to a [Uint8List].
+ Uint8List toTypedList() => Uint8List.fromList(this);
+}
+
+extension ListUint8ListX on List {
+ /// Reduce a [List] of [Uint8List] to a [Uint8List].
+ Uint8List combine() {
+ if (isEmpty) return Uint8List(0);
+ return reduce((value, element) => value.plus(element));
+ }
+}
+
+extension StringX on String {
+ /// Converts a [String] to a [Uint8List] using the specified [Encoding].
+ Uint8List toBytes({final Encoding from = Encoding.utf16}) {
+ Uint8List bytes;
+ switch (from) {
+ case Encoding.utf8:
+ bytes = utf8.encode(this).toTypedList();
+ break;
+ case Encoding.utf16:
+ bytes = runes.toList().toTypedList();
+ break;
+ case Encoding.base64:
+ bytes = base64.decode(this);
+ break;
+ case Encoding.base16:
+ assert(length.isEven, 'String needs to be an even length.');
+ bytes = List.generate(
+ length ~/ 2,
+ (i) => int.parse(substring(i * 2, (i * 2) + 2), radix: 16),
+ ).toList().toTypedList();
+ }
+ return bytes;
+ }
+}
+
+extension Uint8ListX on Uint8List {
+ /// Converts a [Uint8List] to a [String] using the specified [Encoding].
+ String toStr({final Encoding to = Encoding.utf16}) {
+ String str;
+ switch (to) {
+ case Encoding.utf8:
+ str = utf8.decode(this);
+ break;
+ case Encoding.utf16:
+ str = String.fromCharCodes(this);
+ break;
+ case Encoding.base64:
+ str = base64.encode(this);
+ break;
+ case Encoding.base16:
+ str = List.generate(
+ length,
+ (i) => this[i].toRadixString(16).padLeft(2, '0'),
+ ).join();
+ }
+ return str;
+ }
+
+ /// Returns a concatenation of this with the other [Uint8List].
+ Uint8List plus(final Uint8List other) => [...this, ...other].toTypedList();
+
+ /// Returns a sublist of this from the [start] index to the [end] index.
+ /// If [end] is greater than the length of the list, it is set to the length
+ Uint8List trySublist(int start, [int? end]) {
+ if (isEmpty) return this;
+
+ int ending = end ?? length;
+ if (ending > length) ending = length;
+
+ return sublist(start, ending);
+ }
+}
diff --git a/packages/native_crypto/lib/src/utils/hash_algorithm.dart b/packages/native_crypto/lib/src/utils/hash_algorithm.dart
new file mode 100644
index 0000000..4538ef5
--- /dev/null
+++ b/packages/native_crypto/lib/src/utils/hash_algorithm.dart
@@ -0,0 +1,51 @@
+// Author: Hugo Pointcheval
+// Email: git@pcl.ovh
+// -----
+// File: hash_algorithm.dart
+// Created Date: 23/05/2022 22:01:59
+// Last Modified: 26/05/2022 22:59:04
+// -----
+// Copyright (c) 2022
+
+import 'dart:typed_data';
+
+import 'package:native_crypto/src/platform.dart';
+import 'package:native_crypto/src/utils/extensions.dart';
+import 'package:native_crypto_platform_interface/native_crypto_platform_interface.dart';
+
+/// Defines the hash algorithms.
+enum HashAlgorithm {
+ sha256,
+ sha384,
+ sha512;
+
+ /// Digest the [data] using this [HashAlgorithm].
+ Future digest(Uint8List data) async {
+ Uint8List? hash;
+ try {
+ hash = await platform.digest(data, name);
+ } catch (e, s) {
+ throw NativeCryptoException(
+ message: '$e',
+ code: NativeCryptoExceptionCode.platform_throws.code,
+ stackTrace: s,
+ );
+ }
+
+ if (hash.isNull) {
+ throw NativeCryptoException(
+ message: 'Failed to digest data! Platform returned null.',
+ code: NativeCryptoExceptionCode.platform_returned_null.code,
+ );
+ }
+
+ if (hash!.isEmpty) {
+ throw NativeCryptoException(
+ message: 'Failed to digest data! Platform returned no data.',
+ code: NativeCryptoExceptionCode.platform_returned_empty_data.code,
+ );
+ }
+
+ return hash;
+ }
+}
diff --git a/packages/native_crypto/lib/src/utils/kdf_algorithm.dart b/packages/native_crypto/lib/src/utils/kdf_algorithm.dart
new file mode 100644
index 0000000..68d6a76
--- /dev/null
+++ b/packages/native_crypto/lib/src/utils/kdf_algorithm.dart
@@ -0,0 +1,11 @@
+// Author: Hugo Pointcheval
+// Email: git@pcl.ovh
+// -----
+// File: kdf_algorithm.dart
+// Created Date: 23/05/2022 22:36:24
+// Last Modified: 26/05/2022 18:53:50
+// -----
+// Copyright (c) 2022
+
+/// Represents different key derivation functions
+enum KdfAlgorithm { pbkdf2 }
diff --git a/packages/native_crypto/pubspec.yaml b/packages/native_crypto/pubspec.yaml
new file mode 100644
index 0000000..72b0d59
--- /dev/null
+++ b/packages/native_crypto/pubspec.yaml
@@ -0,0 +1,52 @@
+name: native_crypto
+description: Fast and secure cryptography for Flutter.
+version: 0.1.1
+
+publish_to: 'none'
+
+environment:
+ sdk: ">=2.17.0 <3.0.0"
+ flutter: ">=2.5.0"
+
+dependencies:
+ flutter:
+ sdk: flutter
+
+ native_crypto_android:
+ git:
+ url: https://github.com/hugo-pcl/native-crypto-flutter.git
+ ref: native_crypto_android-v0.1.1
+ path: packages/native_crypto_android
+
+ native_crypto_ios:
+ git:
+ url: https://github.com/hugo-pcl/native-crypto-flutter.git
+ ref: native_crypto_ios-v0.1.1
+ path: packages/native_crypto_ios
+
+ native_crypto_platform_interface:
+ git:
+ url: https://github.com/hugo-pcl/native-crypto-flutter.git
+ ref: native_crypto_platform_interface-v0.1.1
+ path: packages/native_crypto_platform_interface
+
+dev_dependencies:
+ flutter_test:
+ sdk: flutter
+
+ mockito: ^5.2.0
+ plugin_platform_interface: ^2.1.2
+
+ wyatt_analysis:
+ git:
+ url: https://git.wyatt-studio.fr/Wyatt-FOSS/wyatt-packages
+ ref: wyatt_analysis-v2.1.0
+ path: packages/wyatt_analysis
+
+flutter:
+ plugin:
+ platforms:
+ android:
+ default_package: native_crypto_android
+ ios:
+ default_package: native_crypto_ios
\ No newline at end of file
diff --git a/packages/native_crypto/test/mocks/mock_native_crypto_platform.dart b/packages/native_crypto/test/mocks/mock_native_crypto_platform.dart
new file mode 100644
index 0000000..6e69cb9
--- /dev/null
+++ b/packages/native_crypto/test/mocks/mock_native_crypto_platform.dart
@@ -0,0 +1,192 @@
+// Author: Hugo Pointcheval
+// Email: git@pcl.ovh
+// -----
+// File: mock_native_crypto_platform.dart
+// Created Date: 25/05/2022 23:34:34
+// Last Modified: 26/05/2022 11:40:24
+// -----
+// Copyright (c) 2022
+
+import 'dart:typed_data';
+
+import 'package:flutter_test/flutter_test.dart';
+import 'package:native_crypto_platform_interface/native_crypto_platform_interface.dart';
+import 'package:plugin_platform_interface/plugin_platform_interface.dart';
+
+class MockNativeCryptoPlatform extends Fake
+ with MockPlatformInterfaceMixin
+ implements NativeCryptoPlatform {
+ Uint8List? data;
+ List? dataAsList;
+ Uint8List? key;
+ String? algorithm;
+ int? bitsCount;
+ String? password;
+ String? salt;
+ int? keyBytesCount;
+ int? iterations;
+
+ Uint8List? Function()? response;
+ List? Function()? responseAsList;
+
+ // ignore: use_setters_to_change_properties
+ void setResponse(Uint8List? Function()? response) {
+ this.response = response;
+ }
+
+ // ignore: use_setters_to_change_properties
+ void setResponseAsList(List? Function()? responseAsList) {
+ this.responseAsList = responseAsList;
+ }
+
+ void setDecryptExpectations({
+ required Uint8List data,
+ required Uint8List key,
+ required String algorithm,
+ }) {
+ this.data = data;
+ this.key = key;
+ this.algorithm = algorithm;
+ }
+
+ @override
+ Future decrypt(
+ Uint8List data,
+ Uint8List key,
+ String algorithm,
+ ) async {
+ expect(data, this.data);
+ expect(key, this.key);
+ expect(algorithm, this.algorithm);
+ return response?.call();
+ }
+
+ void setDecryptAsListExpectations({
+ required List data,
+ required Uint8List key,
+ required String algorithm,
+ }) {
+ dataAsList = data;
+ this.key = key;
+ this.algorithm = algorithm;
+ }
+
+ @override
+ Future decryptAsList(
+ List data,
+ Uint8List key,
+ String algorithm,
+ ) async {
+ expect(data, dataAsList);
+ expect(key, this.key);
+ expect(algorithm, this.algorithm);
+
+ return response?.call();
+ }
+
+ void setDigestExpectations({
+ required Uint8List data,
+ required String algorithm,
+ }) {
+ this.data = data;
+ this.algorithm = algorithm;
+ }
+
+ @override
+ Future digest(Uint8List data, String algorithm) async {
+ expect(data, this.data);
+ expect(algorithm, this.algorithm);
+
+ return response?.call();
+ }
+
+ void setEncryptExpectations({
+ required Uint8List data,
+ required Uint8List key,
+ required String algorithm,
+ }) {
+ this.data = data;
+ this.key = key;
+ this.algorithm = algorithm;
+ }
+
+ @override
+ Future encrypt(
+ Uint8List data,
+ Uint8List key,
+ String algorithm,
+ ) async {
+ expect(data, this.data);
+ expect(key, this.key);
+ expect(algorithm, this.algorithm);
+
+ return response?.call();
+ }
+
+ void setEncryptAsListExpectations({
+ required Uint8List data,
+ required Uint8List key,
+ required String algorithm,
+ }) =>
+ setEncryptExpectations(
+ data: data,
+ key: key,
+ algorithm: algorithm,
+ );
+
+ @override
+ Future?> encryptAsList(
+ Uint8List data,
+ Uint8List key,
+ String algorithm,
+ ) async {
+ expect(data, this.data);
+ expect(key, this.key);
+ expect(algorithm, this.algorithm);
+
+ return responseAsList?.call();
+ }
+
+ // ignore: use_setters_to_change_properties
+ void setGenerateKeyExpectations({required int bitsCount}) {
+ this.bitsCount = bitsCount;
+ }
+
+ @override
+ Future generateSecretKey(int bitsCount) async {
+ expect(bitsCount, this.bitsCount);
+
+ return response?.call();
+ }
+
+ void setPbkdf2Expectations({
+ required String password,
+ required String salt,
+ required int keyBytesCount,
+ required int iterations,
+ required String algorithm,
+ }) {
+ this.password = password;
+ this.salt = salt;
+ this.iterations = iterations;
+ this.keyBytesCount = keyBytesCount;
+ this.algorithm = algorithm;
+ }
+
+ @override
+ Future pbkdf2(
+ String password,
+ String salt,
+ int keyBytesCount,
+ int iterations,
+ String algorithm,
+ ) async {
+ expect(password, this.password);
+ expect(salt, this.salt);
+ expect(keyBytesCount, this.keyBytesCount);
+ expect(iterations, this.iterations);
+ expect(algorithm, this.algorithm);
+
+ return response?.call();
+ }
+}
diff --git a/packages/native_crypto/test/src/aes_cipher_test.dart b/packages/native_crypto/test/src/aes_cipher_test.dart
new file mode 100644
index 0000000..f1d0f39
--- /dev/null
+++ b/packages/native_crypto/test/src/aes_cipher_test.dart
@@ -0,0 +1,323 @@
+// Author: Hugo Pointcheval
+// Email: git@pcl.ovh
+// -----
+// File: aes_cipher_test.dart
+// Created Date: 26/05/2022 23:20:53
+// Last Modified: 27/05/2022 16:39:44
+// -----
+// Copyright (c) 2022
+
+import 'dart:typed_data';
+
+import 'package:flutter/services.dart';
+import 'package:flutter_test/flutter_test.dart';
+import 'package:native_crypto/native_crypto.dart';
+import 'package:native_crypto_platform_interface/native_crypto_platform_interface.dart';
+
+import '../mocks/mock_native_crypto_platform.dart';
+
+void main() {
+ final MockNativeCryptoPlatform mock = MockNativeCryptoPlatform();
+ NativeCryptoPlatform.instance = mock;
+
+ setUp(() {
+ Cipher.bytesCountPerChunk = Cipher.defaultBytesCountPerChunk;
+ });
+
+ group('Constructor', () {
+ test('throws on invalid key length', () {
+ expect(
+ () => AES(SecretKey(Uint8List(0))),
+ throwsA(
+ isA()
+ .having(
+ (e) => e.code,
+ 'code',
+ 'invalid_key_length',
+ )
+ .having(
+ (e) => e.message,
+ 'message',
+ contains('Invalid key'),
+ ),
+ ),
+ );
+ });
+
+ test('creates a valid instance', () {
+ expect(
+ AES(
+ SecretKey(Uint8List(16)),
+ ),
+ isA(),
+ );
+ });
+ });
+
+ group('encrypt', () {
+ test('returns a valid cipher text wrapper', () async {
+ mock
+ ..setEncryptExpectations(
+ data: Uint8List(16),
+ key: Uint8List(16),
+ algorithm: 'aes',
+ )
+ ..setResponse(() => Uint8List(16 + 28));
+
+ final aes = AES(SecretKey(Uint8List(16)));
+
+ expect(
+ await aes.encrypt(Uint8List(16)),
+ isA().having((e) => e.isSingle, 'is single', isTrue),
+ );
+ });
+
+ test('returns a valid cipher text with multiple chunks', () async {
+ mock
+ ..setEncryptExpectations(
+ data: Uint8List(16),
+ key: Uint8List(16),
+ algorithm: 'aes',
+ )
+ ..setResponse(() => Uint8List(16 + 28)); // Returns 1 encrypted chunk
+ Cipher.bytesCountPerChunk = 16;
+ final aes = AES(SecretKey(Uint8List(16)));
+
+ expect(
+ await aes.encrypt(Uint8List(16 * 3)),
+ isA().having((e) => e.isList, 'is list', isTrue),
+ );
+ });
+
+ test('handles returning empty list', () async {
+ mock
+ ..setEncryptExpectations(
+ data: Uint8List(16),
+ key: Uint8List(16),
+ algorithm: 'aes',
+ )
+ ..setResponse(() => Uint8List(0));
+
+ final aes = AES(SecretKey(Uint8List(16)));
+
+ await expectLater(
+ () => aes.encrypt(Uint8List(16)),
+ throwsA(
+ isA().having(
+ (e) => e.code,
+ 'code',
+ 'platform_returned_empty_data',
+ ),
+ ),
+ );
+ });
+
+ test('handles returning null', () async {
+ mock
+ ..setEncryptExpectations(
+ data: Uint8List(16),
+ key: Uint8List(16),
+ algorithm: 'aes',
+ )
+ ..setResponse(() => null);
+
+ final aes = AES(SecretKey(Uint8List(16)));
+
+ await expectLater(
+ () => aes.encrypt(Uint8List(16)),
+ throwsA(
+ isA().having(
+ (e) => e.code,
+ 'code',
+ 'platform_returned_null',
+ ),
+ ),
+ );
+ });
+
+ test('handles throwing PlatformException', () async {
+ mock
+ ..setEncryptExpectations(
+ data: Uint8List(16),
+ key: Uint8List(16),
+ algorithm: 'aes',
+ )
+ ..setResponse(
+ () => throw PlatformException(
+ code: 'native_crypto',
+ message: 'dummy error',
+ ),
+ );
+
+ final aes = AES(SecretKey(Uint8List(16)));
+
+ await expectLater(
+ () => aes.encrypt(Uint8List(16)),
+ throwsA(
+ isA()
+ .having(
+ (e) => e.message,
+ 'message',
+ contains(
+ 'PlatformException(native_crypto, dummy error, null, null)',
+ ),
+ )
+ .having(
+ (e) => e.code,
+ 'code',
+ 'platform_throws',
+ ),
+ ),
+ );
+ });
+ });
+
+ group('decrypt', () {
+ test('returns a valid Uint8List', () async {
+ mock
+ ..setDecryptExpectations(
+ data: Uint8List(16 + 28),
+ key: Uint8List(16),
+ algorithm: 'aes',
+ )
+ ..setResponse(() => Uint8List(16));
+
+ final aes = AES(SecretKey(Uint8List(16)));
+ final bytes = Uint8List(16 + 28);
+ final wrapper = CipherTextWrapper.fromBytes(
+ bytes,
+ ivLength: 12,
+ tagLength: 16,
+ );
+
+ expect(
+ await aes.decrypt(wrapper),
+ isA().having((e) => e.length, 'length', 16),
+ );
+ });
+
+ test('returns a valid Uint8List on decrypting multiple chunks', () async {
+ const int chunkSize = 8;
+ mock
+ ..setDecryptExpectations(
+ data: Uint8List(chunkSize + 28),
+ key: Uint8List(16),
+ algorithm: 'aes',
+ )
+ ..setResponse(() => Uint8List(chunkSize));
+ Cipher.bytesCountPerChunk = chunkSize;
+ final aes = AES(SecretKey(Uint8List(16)));
+ final bytes = Uint8List((chunkSize + 28) * 3);
+ final wrapper = CipherTextWrapper.fromBytes(
+ bytes,
+ ivLength: 12,
+ tagLength: 16,
+ );
+
+ expect(
+ await aes.decrypt(wrapper),
+ isA().having((e) => e.length, 'length', chunkSize * 3),
+ );
+ });
+
+ test('handles returning empty list', () async {
+ mock
+ ..setDecryptExpectations(
+ data: Uint8List(16 + 28),
+ key: Uint8List(16),
+ algorithm: 'aes',
+ )
+ ..setResponse(() => Uint8List(0));
+
+ final aes = AES(SecretKey(Uint8List(16)));
+ final bytes = Uint8List(16 + 28);
+ final wrapper = CipherTextWrapper.fromBytes(
+ bytes,
+ ivLength: 12,
+ tagLength: 16,
+ );
+
+ await expectLater(
+ () => aes.decrypt(wrapper),
+ throwsA(
+ isA().having(
+ (e) => e.code,
+ 'code',
+ 'platform_returned_empty_data',
+ ),
+ ),
+ );
+ });
+
+ test('handles returning null', () async {
+ mock
+ ..setDecryptExpectations(
+ data: Uint8List(16 + 28),
+ key: Uint8List(16),
+ algorithm: 'aes',
+ )
+ ..setResponse(() => null);
+
+ final aes = AES(SecretKey(Uint8List(16)));
+ final bytes = Uint8List(16 + 28);
+ final wrapper = CipherTextWrapper.fromBytes(
+ bytes,
+ ivLength: 12,
+ tagLength: 16,
+ );
+
+ await expectLater(
+ () => aes.decrypt(wrapper),
+ throwsA(
+ isA().having(
+ (e) => e.code,
+ 'code',
+ 'platform_returned_null',
+ ),
+ ),
+ );
+ });
+
+ test('handles throwing PlatformException', () async {
+ mock
+ ..setDecryptExpectations(
+ data: Uint8List(16 + 28),
+ key: Uint8List(16),
+ algorithm: 'aes',
+ )
+ ..setResponse(
+ () => throw PlatformException(
+ code: 'native_crypto',
+ message: 'dummy error',
+ ),
+ );
+
+ final aes = AES(SecretKey(Uint8List(16)));
+ final bytes = Uint8List(16 + 28);
+ final wrapper = CipherTextWrapper.fromBytes(
+ bytes,
+ ivLength: 12,
+ tagLength: 16,
+ );
+
+ await expectLater(
+ () => aes.decrypt(wrapper),
+ throwsA(
+ isA()
+ .having(
+ (e) => e.message,
+ 'message',
+ contains(
+ 'PlatformException(native_crypto, dummy error, null, null)',
+ ),
+ )
+ .having(
+ (e) => e.code,
+ 'code',
+ 'platform_throws',
+ ),
+ ),
+ );
+ });
+ });
+}
diff --git a/packages/native_crypto/test/src/cipher_text_test.dart b/packages/native_crypto/test/src/cipher_text_test.dart
new file mode 100644
index 0000000..16d98a5
--- /dev/null
+++ b/packages/native_crypto/test/src/cipher_text_test.dart
@@ -0,0 +1,192 @@
+// Author: Hugo Pointcheval
+// Email: git@pcl.ovh
+// -----
+// File: cipher_text_test.dart
+// Created Date: 26/05/2022 20:45:38
+// Last Modified: 26/05/2022 21:29:51
+// -----
+// Copyright (c) 2022
+
+import 'dart:typed_data';
+
+import 'package:flutter_test/flutter_test.dart';
+import 'package:native_crypto/native_crypto.dart';
+
+void main() {
+ setUp(() {
+ Cipher.bytesCountPerChunk = Cipher.defaultBytesCountPerChunk;
+ });
+
+ group('fromBytes', () {
+ test('throws if length is not the one expected', () {
+ final Uint8List bytes = Uint8List.fromList([1, 2, 3, 4, 5]);
+ expect(
+ () => CipherText.fromBytes(
+ bytes,
+ ivLength: 1,
+ messageLength: 1,
+ tagLength: 1,
+ ),
+ throwsA(
+ isA()
+ .having(
+ (e) => e.code,
+ 'code',
+ 'invalid_argument',
+ )
+ .having(
+ (e) => e.message,
+ 'message',
+ contains('Invalid cipher text length'),
+ ),
+ ),
+ );
+ });
+
+ test('throws if length is bigger than expected', () {
+ final Uint8List bytes = Uint8List.fromList([1, 3, 3, 3, 1]);
+ Cipher.bytesCountPerChunk = 2;
+ expect(
+ () => CipherText.fromBytes(
+ bytes,
+ ivLength: 1,
+ messageLength: 3,
+ tagLength: 1,
+ ),
+ throwsA(
+ isA()
+ .having(
+ (e) => e.code,
+ 'code',
+ 'invalid_argument',
+ )
+ .having(
+ (e) => e.message,
+ 'message',
+ contains('Cipher text is too big'),
+ ),
+ ),
+ );
+ });
+
+ test('throws if data is empty', () {
+ final Uint8List bytes = Uint8List(0);
+ expect(
+ () => CipherText.fromBytes(
+ bytes,
+ ivLength: 1,
+ messageLength: 3,
+ tagLength: 1,
+ ),
+ throwsA(
+ isA()
+ .having(
+ (e) => e.code,
+ 'code',
+ 'invalid_argument',
+ )
+ .having(
+ (e) => e.message,
+ 'message',
+ contains('Passed data is empty'),
+ ),
+ ),
+ );
+ });
+
+ test('throws if one of the length is negative', () {
+ final Uint8List bytes = Uint8List(0);
+ expect(
+ () => CipherText.fromBytes(
+ bytes,
+ ivLength: -1,
+ messageLength: 1,
+ tagLength: 1,
+ ),
+ throwsA(
+ isA()
+ .having(
+ (e) => e.code,
+ 'code',
+ 'invalid_argument',
+ )
+ .having(
+ (e) => e.message,
+ 'message',
+ contains('Invalid length'),
+ ),
+ ),
+ );
+ });
+ });
+
+ group('get.cipherAlgorithm', () {
+ test('throws if not set', () {
+ final CipherText cipherText = CipherText.fromBytes(
+ Uint8List.fromList([1, 2, 3]),
+ ivLength: 1,
+ messageLength: 1,
+ tagLength: 1,
+ );
+ expect(
+ () => cipherText.cipherAlgorithm,
+ throwsA(
+ isA()
+ .having(
+ (e) => e.code,
+ 'code',
+ 'invalid_cipher',
+ )
+ .having(
+ (e) => e.message,
+ 'message',
+ contains('Cipher algorithm is not specified'),
+ ),
+ ),
+ );
+ });
+
+ test('returns the expected value', () {
+ final CipherText cipherText = CipherText.fromBytes(
+ Uint8List.fromList([1, 2, 3]),
+ ivLength: 1,
+ messageLength: 1,
+ tagLength: 1,
+ cipherAlgorithm: CipherAlgorithm.aes,
+ );
+ expect(cipherText.cipherAlgorithm, CipherAlgorithm.aes);
+ });
+ });
+
+ group('Lengths', () {
+ test('get.ivLength returns the expected value', () {
+ final CipherText cipherText = CipherText.fromBytes(
+ Uint8List.fromList([1, 2, 3]),
+ ivLength: 1,
+ messageLength: 1,
+ tagLength: 1,
+ );
+ expect(cipherText.ivLength, 1);
+ });
+
+ test('get.messageLength returns the expected value', () {
+ final CipherText cipherText = CipherText.fromBytes(
+ Uint8List.fromList([1, 2, 3]),
+ ivLength: 1,
+ messageLength: 1,
+ tagLength: 1,
+ );
+ expect(cipherText.messageLength, 1);
+ });
+
+ test('get.tagLength returns the expected value', () {
+ final CipherText cipherText = CipherText.fromBytes(
+ Uint8List.fromList([1, 2, 3]),
+ ivLength: 1,
+ messageLength: 1,
+ tagLength: 1,
+ );
+ expect(cipherText.tagLength, 1);
+ });
+ });
+}
diff --git a/packages/native_crypto/test/src/cipher_text_wrapper_test.dart b/packages/native_crypto/test/src/cipher_text_wrapper_test.dart
new file mode 100644
index 0000000..8dc0116
--- /dev/null
+++ b/packages/native_crypto/test/src/cipher_text_wrapper_test.dart
@@ -0,0 +1,349 @@
+// Author: Hugo Pointcheval
+// Email: git@pcl.ovh
+// -----
+// File: cipher_text_wrapper_test.dart
+// Created Date: 26/05/2022 21:35:41
+// Last Modified: 27/05/2022 13:46:54
+// -----
+// Copyright (c) 2022
+
+import 'dart:typed_data';
+
+import 'package:flutter_test/flutter_test.dart';
+import 'package:native_crypto/native_crypto.dart';
+
+void main() {
+ late CipherText single;
+ late List list;
+
+ setUp(() {
+ Cipher.bytesCountPerChunk = Cipher.defaultBytesCountPerChunk;
+ single = CipherText.fromBytes(
+ Uint8List.fromList([1, 2, 3]),
+ ivLength: 1,
+ messageLength: 1,
+ tagLength: 1,
+ );
+ list = [
+ CipherText.fromBytes(
+ Uint8List.fromList([1, 2, 3]),
+ ivLength: 1,
+ messageLength: 1,
+ tagLength: 1,
+ ),
+ CipherText.fromBytes(
+ Uint8List.fromList([4, 5, 6]),
+ ivLength: 1,
+ messageLength: 1,
+ tagLength: 1,
+ ),
+ ];
+ });
+
+ group('single', () {
+ test('makes isSingle true', () {
+ final wrapper = CipherTextWrapper.single(single);
+ expect(wrapper.isSingle, isTrue);
+ });
+
+ test('makes isList false', () {
+ final wrapper = CipherTextWrapper.single(single);
+ expect(wrapper.isList, isFalse);
+ });
+
+ test('makes CipherText the single value', () {
+ final wrapper = CipherTextWrapper.single(single);
+ expect(wrapper.single, single);
+ });
+
+ test('throws when trying to get list', () {
+ final wrapper = CipherTextWrapper.single(single);
+ expect(
+ () => wrapper.list,
+ throwsA(
+ isA()
+ .having(
+ (e) => e.code,
+ 'code',
+ 'invalid_data',
+ )
+ .having(
+ (e) => e.message,
+ 'message',
+ contains('is not list'),
+ ),
+ ),
+ );
+ });
+
+ test('makes wrapper returns bytes of CipherText', () {
+ final wrapper = CipherTextWrapper.single(single);
+ expect(wrapper.bytes, single.bytes);
+ });
+
+ test('makes chunkCount = 1', () {
+ final wrapper = CipherTextWrapper.single(single);
+ expect(wrapper.chunkCount, 1);
+ });
+
+ test('makes unwrap() returns only CipherText', () {
+ final wrapper = CipherTextWrapper.single(single);
+ expect(wrapper.unwrap(), single);
+ });
+
+ test('makes unwrap() throws when trying to unwrap List', () {
+ final wrapper = CipherTextWrapper.single(single);
+ expect(
+ () => wrapper.unwrap>(),
+ throwsA(
+ isA()
+ .having(
+ (e) => e.code,
+ 'code',
+ 'invalid_data',
+ )
+ .having(
+ (e) => e.message,
+ 'message',
+ contains('you should use unwrap'),
+ ),
+ ),
+ );
+ });
+
+ test('makes adding is not supported', () {
+ final wrapper = CipherTextWrapper.single(single);
+ expect(
+ () => wrapper.add(single),
+ throwsA(
+ isA()
+ .having(
+ (e) => e.code,
+ 'code',
+ 'invalid_data',
+ )
+ .having(
+ (e) => e.message,
+ 'message',
+ contains('is already single'),
+ ),
+ ),
+ );
+ });
+ });
+
+ group('list', () {
+ test('makes isList true', () {
+ final wrapper = CipherTextWrapper.list(list);
+ expect(wrapper.isList, isTrue);
+ });
+
+ test('makes isSingle false', () {
+ final wrapper = CipherTextWrapper.list(list);
+ expect(wrapper.isSingle, isFalse);
+ });
+
+ test('makes List the list value', () {
+ final wrapper = CipherTextWrapper.list(list);
+ expect(wrapper.list, list);
+ });
+
+ test('throws when trying to get single', () {
+ final wrapper = CipherTextWrapper.list(list);
+ expect(
+ () => wrapper.single,
+ throwsA(
+ isA()
+ .having(
+ (e) => e.code,
+ 'code',
+ 'invalid_data',
+ )
+ .having(
+ (e) => e.message,
+ 'message',
+ contains('is not single'),
+ ),
+ ),
+ );
+ });
+
+ test('makes wrapper returns bytes of all CipherText joined', () {
+ final wrapper = CipherTextWrapper.list(list);
+ expect(wrapper.bytes, Uint8List.fromList([1, 2, 3, 4, 5, 6]));
+ });
+
+ test('makes chunkCount = 2', () {
+ final wrapper = CipherTextWrapper.list(list);
+ expect(wrapper.chunkCount, 2);
+ });
+
+ test('makes unwrap() returns List', () {
+ final wrapper = CipherTextWrapper.list(list);
+ expect(wrapper.unwrap>(), list);
+ });
+
+ test('makes unwrap() throws when trying to unwrap single', () {
+ final wrapper = CipherTextWrapper.list(list);
+ expect(
+ () => wrapper.unwrap(),
+ throwsA(
+ isA()
+ .having(
+ (e) => e.code,
+ 'code',
+ 'invalid_data',
+ )
+ .having(
+ (e) => e.message,
+ 'message',
+ contains('you should use unwrap'),
+ ),
+ ),
+ );
+ });
+
+ test('makes adding is supported', () {
+ final originalList = List.from(list);
+ final wrapper = CipherTextWrapper.list(list)..add(single);
+ printOnFailure(list.length.toString());
+ expect(wrapper.list, [...originalList, single]);
+ });
+ });
+
+ group('empty', () {
+ test('makes isList true', () {
+ final wrapper = CipherTextWrapper.empty();
+ expect(wrapper.isList, isTrue);
+ });
+
+ test('makes isSingle false', () {
+ final wrapper = CipherTextWrapper.empty();
+ expect(wrapper.isSingle, isFalse);
+ });
+
+ test('makes List the list value', () {
+ final wrapper = CipherTextWrapper.empty();
+ expect(wrapper.list, []);
+ });
+
+ test('throws when trying to get single', () {
+ final wrapper = CipherTextWrapper.empty();
+ expect(
+ () => wrapper.single,
+ throwsA(
+ isA()
+ .having(
+ (e) => e.code,
+ 'code',
+ 'invalid_data',
+ )
+ .having(
+ (e) => e.message,
+ 'message',
+ contains('is not single'),
+ ),
+ ),
+ );
+ });
+
+ test('makes wrapper returns empty bytes', () {
+ final wrapper = CipherTextWrapper.empty();
+ expect(wrapper.bytes, Uint8List.fromList([]));
+ });
+
+ test('makes chunkCount = 0', () {
+ final wrapper = CipherTextWrapper.empty();
+ expect(wrapper.chunkCount, 0);
+ });
+
+ test('makes unwrap() returns empty List', () {
+ final wrapper = CipherTextWrapper.empty();
+ expect(wrapper.unwrap>(), []);
+ });
+
+ test('makes unwrap() throws when trying to unwrap single', () {
+ final wrapper = CipherTextWrapper.empty();
+ expect(
+ () => wrapper.unwrap(),
+ throwsA(
+ isA()
+ .having(
+ (e) => e.code,
+ 'code',
+ 'invalid_data',
+ )
+ .having(
+ (e) => e.message,
+ 'message',
+ contains('you should use unwrap'),
+ ),
+ ),
+ );
+ });
+
+ test('makes adding is supported', () {
+ final wrapper = CipherTextWrapper.empty()..add(single);
+ expect(wrapper.list, [single]);
+ });
+ });
+
+ group('fromBytes', () {
+ test('creates single from bytes when no too big', () {
+ final wrapper = CipherTextWrapper.fromBytes(
+ Uint8List.fromList([1, 2, 3]),
+ ivLength: 1,
+ tagLength: 1,
+ );
+ expect(wrapper.isSingle, isTrue);
+ expect(wrapper.single, single);
+ });
+
+ test('creates list from bytes when too big', () {
+ Cipher.bytesCountPerChunk = 1;
+ final wrapper = CipherTextWrapper.fromBytes(
+ Uint8List.fromList([1, 2, 3, 4, 5, 6]),
+ ivLength: 1,
+ tagLength: 1,
+ );
+ expect(wrapper.isList, isTrue);
+ expect(wrapper.list, list);
+ });
+
+ test('modifies Cipher.bytesCountPerChunk', () {
+ expect(Cipher.bytesCountPerChunk, Cipher.defaultBytesCountPerChunk);
+ CipherTextWrapper.fromBytes(
+ Uint8List.fromList([1, 2, 3]),
+ ivLength: 1,
+ tagLength: 1,
+ chunkSize: 3,
+ );
+ expect(Cipher.bytesCountPerChunk, 3);
+ });
+
+ test('throws if trying to build list with bad parameters', () {
+ Cipher.bytesCountPerChunk = 1; // length of a message
+
+ expect(
+ () => CipherTextWrapper.fromBytes(
+ Uint8List.fromList([1, 2, 3, 4, 5, 6]),
+ ivLength: 2,
+ tagLength: 1,
+ ),
+ throwsA(
+ isA()
+ .having(
+ (e) => e.code,
+ 'code',
+ 'invalid_argument',
+ )
+ .having(
+ (e) => e.message,
+ 'message',
+ contains('on chunk #'),
+ ),
+ ),
+ );
+ });
+ });
+}
diff --git a/packages/native_crypto/test/src/hash_algorithm_test.dart b/packages/native_crypto/test/src/hash_algorithm_test.dart
new file mode 100644
index 0000000..b7911b1
--- /dev/null
+++ b/packages/native_crypto/test/src/hash_algorithm_test.dart
@@ -0,0 +1,128 @@
+// Author: Hugo Pointcheval
+// Email: git@pcl.ovh
+// -----
+// File: hash_algorithm_test.dart
+// Created Date: 26/05/2022 22:28:53
+// Last Modified: 26/05/2022 23:03:03
+// -----
+// Copyright (c) 2022
+
+import 'dart:typed_data';
+
+import 'package:flutter/services.dart';
+import 'package:flutter_test/flutter_test.dart';
+import 'package:native_crypto/src/utils/hash_algorithm.dart';
+import 'package:native_crypto_platform_interface/native_crypto_platform_interface.dart';
+
+import '../mocks/mock_native_crypto_platform.dart';
+
+void main() {
+ final MockNativeCryptoPlatform mock = MockNativeCryptoPlatform();
+ NativeCryptoPlatform.instance = mock;
+
+ group('name', () {
+ test('is sha256 for HashAlgorithm.sha256', () {
+ expect(HashAlgorithm.sha256.name, 'sha256');
+ });
+ test('is sha384 for HashAlgorithm.sha384', () {
+ expect(HashAlgorithm.sha384.name, 'sha384');
+ });
+ test('is sha512 for HashAlgorithm.sha512', () {
+ expect(HashAlgorithm.sha512.name, 'sha512');
+ });
+ });
+
+ group('digest', () {
+ test('handles returning empty list', () async {
+ mock
+ ..setDigestExpectations(
+ data: Uint8List.fromList([1, 2, 3]),
+ algorithm: 'sha256',
+ )
+ ..setResponse(() => Uint8List(0));
+
+ await expectLater(
+ () => HashAlgorithm.sha256.digest(Uint8List.fromList([1, 2, 3])),
+ throwsA(
+ isA().having(
+ (e) => e.code,
+ 'code',
+ 'platform_returned_empty_data',
+ ),
+ ),
+ );
+ });
+
+ test('handles returning null', () async {
+ mock
+ ..setDigestExpectations(
+ data: Uint8List.fromList([1, 2, 3]),
+ algorithm: 'sha256',
+ )
+ ..setResponse(() => null);
+
+ await expectLater(
+ () => HashAlgorithm.sha256.digest(Uint8List.fromList([1, 2, 3])),
+ throwsA(
+ isA().having(
+ (e) => e.code,
+ 'code',
+ 'platform_returned_null',
+ ),
+ ),
+ );
+ });
+
+ test('handles throwing PlatformException', () async {
+ mock
+ ..setDigestExpectations(
+ data: Uint8List.fromList([1, 2, 3]),
+ algorithm: 'sha256',
+ )
+ ..setResponse(
+ () => throw PlatformException(
+ code: 'native_crypto',
+ message: 'dummy error',
+ ),
+ );
+
+ await expectLater(
+ () => HashAlgorithm.sha256.digest(Uint8List.fromList([1, 2, 3])),
+ throwsA(
+ isA()
+ .having(
+ (e) => e.message,
+ 'message',
+ 'PlatformException(native_crypto, dummy error, null, null)',
+ )
+ .having(
+ (e) => e.code,
+ 'code',
+ 'platform_throws',
+ ),
+ ),
+ );
+ });
+
+ test('returns data on success', () async {
+ final hash = Uint8List.fromList([4, 5, 6]);
+ mock
+ ..setDigestExpectations(
+ data: Uint8List.fromList([1, 2, 3]),
+ algorithm: 'sha256',
+ )
+ ..setResponse(() => hash);
+
+ final result = await HashAlgorithm.sha256.digest(
+ Uint8List.fromList(
+ [1, 2, 3],
+ ),
+ );
+
+ expect(
+ result,
+ hash,
+ );
+ });
+ });
+}
diff --git a/packages/native_crypto/test/src/pbkdf2_test.dart b/packages/native_crypto/test/src/pbkdf2_test.dart
new file mode 100644
index 0000000..f0ae084
--- /dev/null
+++ b/packages/native_crypto/test/src/pbkdf2_test.dart
@@ -0,0 +1,280 @@
+// Author: Hugo Pointcheval
+// Email: git@pcl.ovh
+// -----
+// File: pbkdf2_test.dart
+// Created Date: 26/05/2022 22:37:27
+// Last Modified: 26/05/2022 23:20:11
+// -----
+// Copyright (c) 2022
+
+import 'dart:typed_data';
+
+import 'package:flutter/services.dart';
+import 'package:flutter_test/flutter_test.dart';
+import 'package:native_crypto/native_crypto.dart';
+import 'package:native_crypto_platform_interface/native_crypto_platform_interface.dart';
+
+import '../mocks/mock_native_crypto_platform.dart';
+
+void main() {
+ final MockNativeCryptoPlatform mock = MockNativeCryptoPlatform();
+ NativeCryptoPlatform.instance = mock;
+
+ group('Constructor', () {
+ test('throws if keyBytesCount is negative', () {
+ expect(
+ () => Pbkdf2(keyBytesCount: -1, iterations: 10000),
+ throwsA(
+ isA()
+ .having(
+ (e) => e.code,
+ 'code',
+ 'invalid_argument',
+ )
+ .having(
+ (e) => e.message,
+ 'message',
+ contains('must be positive'),
+ ),
+ ),
+ );
+ });
+
+ test('throws if iterations is negative or 0', () {
+ expect(
+ () => Pbkdf2(keyBytesCount: 32, iterations: -1),
+ throwsA(
+ isA()
+ .having(
+ (e) => e.code,
+ 'code',
+ 'invalid_argument',
+ )
+ .having(
+ (e) => e.message,
+ 'message',
+ contains('must be strictly positive'),
+ ),
+ ),
+ );
+ });
+ });
+
+ group('derive', () {
+ test('throws if password is null', () async {
+ final pbkdf2 = Pbkdf2(keyBytesCount: 32, iterations: 10000);
+ await expectLater(
+ () => pbkdf2.derive(
+ salt: 'salt',
+ ),
+ throwsA(
+ isA()
+ .having(
+ (e) => e.code,
+ 'code',
+ 'invalid_argument',
+ )
+ .having(
+ (e) => e.message,
+ 'message',
+ contains('cannot be null'),
+ ),
+ ),
+ );
+ });
+
+ test('throws if salt is null', () async {
+ final pbkdf2 = Pbkdf2(keyBytesCount: 32, iterations: 10000);
+ await expectLater(
+ () => pbkdf2.derive(
+ password: 'password',
+ ),
+ throwsA(
+ isA()
+ .having(
+ (e) => e.code,
+ 'code',
+ 'invalid_argument',
+ )
+ .having(
+ (e) => e.message,
+ 'message',
+ contains('cannot be null'),
+ ),
+ ),
+ );
+ });
+
+ test('handles returning empty list', () async {
+ mock
+ ..setPbkdf2Expectations(
+ password: 'password',
+ salt: 'salt',
+ keyBytesCount: 32,
+ iterations: 10000,
+ algorithm: 'sha256',
+ )
+ ..setResponse(() => Uint8List(0));
+
+ final pbkdf2 = Pbkdf2(keyBytesCount: 32, iterations: 10000);
+
+ await expectLater(
+ () => pbkdf2.derive(
+ password: 'password',
+ salt: 'salt',
+ ),
+ throwsA(
+ isA().having(
+ (e) => e.code,
+ 'code',
+ 'platform_returned_empty_data',
+ ),
+ ),
+ );
+ });
+
+ test('handles returning null', () async {
+ mock
+ ..setPbkdf2Expectations(
+ password: 'password',
+ salt: 'salt',
+ keyBytesCount: 32,
+ iterations: 10000,
+ algorithm: 'sha256',
+ )
+ ..setResponse(() => null);
+
+ final pbkdf2 = Pbkdf2(keyBytesCount: 32, iterations: 10000);
+
+ await expectLater(
+ () => pbkdf2.derive(
+ password: 'password',
+ salt: 'salt',
+ ),
+ throwsA(
+ isA().having(
+ (e) => e.code,
+ 'code',
+ 'platform_returned_null',
+ ),
+ ),
+ );
+ });
+
+ test('handles returning data with wrong length', () async {
+ mock
+ ..setPbkdf2Expectations(
+ password: 'password',
+ salt: 'salt',
+ keyBytesCount: 32,
+ iterations: 10000,
+ algorithm: 'sha256',
+ )
+ ..setResponse(() => Uint8List(33));
+
+ final pbkdf2 = Pbkdf2(keyBytesCount: 32, iterations: 10000);
+
+ await expectLater(
+ () => pbkdf2.derive(
+ password: 'password',
+ salt: 'salt',
+ ),
+ throwsA(
+ isA().having(
+ (e) => e.code,
+ 'code',
+ 'platform_returned_invalid_data',
+ ),
+ ),
+ );
+ });
+
+ test('handles throwing PlatformException', () async {
+ mock
+ ..setPbkdf2Expectations(
+ password: 'password',
+ salt: 'salt',
+ keyBytesCount: 32,
+ iterations: 10000,
+ algorithm: 'sha256',
+ )
+ ..setResponse(
+ () => throw PlatformException(
+ code: 'native_crypto',
+ message: 'dummy error',
+ ),
+ );
+
+ final pbkdf2 = Pbkdf2(keyBytesCount: 32, iterations: 10000);
+
+ await expectLater(
+ () => pbkdf2.derive(
+ password: 'password',
+ salt: 'salt',
+ ),
+ throwsA(
+ isA()
+ .having(
+ (e) => e.message,
+ 'message',
+ 'PlatformException(native_crypto, dummy error, null, null)',
+ )
+ .having(
+ (e) => e.code,
+ 'code',
+ 'platform_throws',
+ ),
+ ),
+ );
+ });
+
+ test('returns SecretKey on success', () async {
+ final data = Uint8List.fromList([1, 2, 3, 4, 5, 6]);
+ final sk = SecretKey(data);
+ mock
+ ..setPbkdf2Expectations(
+ password: 'password',
+ salt: 'salt',
+ keyBytesCount: 6,
+ iterations: 10000,
+ algorithm: 'sha256',
+ )
+ ..setResponse(() => data);
+
+ final pbkdf = Pbkdf2(keyBytesCount: 6, iterations: 10000);
+ final result = await pbkdf.derive(
+ password: 'password',
+ salt: 'salt',
+ );
+
+ expect(
+ result,
+ sk,
+ );
+ });
+
+ test('return empty SecretKey when keyBytesCount is set to 0', () async {
+ final sk = SecretKey(Uint8List(0));
+ mock
+ ..setPbkdf2Expectations(
+ password: 'password',
+ salt: 'salt',
+ keyBytesCount: 0,
+ iterations: 10000,
+ algorithm: 'sha256',
+ )
+ ..setResponse(() => Uint8List(0));
+
+ final pbkdf = Pbkdf2(keyBytesCount: 0, iterations: 10000);
+ final result = await pbkdf.derive(
+ password: 'password',
+ salt: 'salt',
+ );
+
+ expect(
+ result,
+ sk,
+ );
+ });
+ });
+}
diff --git a/packages/native_crypto/test/src/secret_key_test.dart b/packages/native_crypto/test/src/secret_key_test.dart
new file mode 100644
index 0000000..df2f159
--- /dev/null
+++ b/packages/native_crypto/test/src/secret_key_test.dart
@@ -0,0 +1,125 @@
+// Author: Hugo Pointcheval
+// Email: git@pcl.ovh
+// -----
+// File: secret_key_test.dart
+// Created Date: 26/05/2022 10:52:41
+// Last Modified: 26/05/2022 22:38:07
+// -----
+// Copyright (c) 2022
+
+import 'dart:typed_data';
+
+import 'package:flutter/services.dart';
+import 'package:flutter_test/flutter_test.dart';
+import 'package:native_crypto/src/keys/secret_key.dart';
+import 'package:native_crypto_platform_interface/native_crypto_platform_interface.dart';
+
+import '../mocks/mock_native_crypto_platform.dart';
+
+void main() {
+ final MockNativeCryptoPlatform mock = MockNativeCryptoPlatform();
+ NativeCryptoPlatform.instance = mock;
+
+ group('Constructors', () {
+ test('handles Uint8List', () {
+ final SecretKey key = SecretKey(Uint8List.fromList([1, 2, 3, 4, 5]));
+
+ expect(key.bytes, Uint8List.fromList([1, 2, 3, 4, 5]));
+ });
+
+ test('handles base16', () {
+ final SecretKey key = SecretKey.fromBase16('0102030405');
+
+ expect(key.bytes, Uint8List.fromList([1, 2, 3, 4, 5]));
+ });
+
+ test('handles base64', () {
+ final SecretKey key = SecretKey.fromBase64('AQIDBAU=');
+
+ expect(key.bytes, Uint8List.fromList([1, 2, 3, 4, 5]));
+ });
+
+ test('handles utf8', () {
+ final SecretKey key = SecretKey.fromUtf8('ABCDE');
+
+ expect(key.bytes, Uint8List.fromList([65, 66, 67, 68, 69]));
+ });
+ });
+
+ group('fromSecureRandom', () {
+ test('handles returning random bytes', () async {
+ mock
+ ..setGenerateKeyExpectations(bitsCount: 5)
+ ..setResponse(() => Uint8List.fromList([1, 2, 3, 4, 5]));
+
+ final SecretKey secretKey = await SecretKey.fromSecureRandom(5);
+
+ expect(
+ secretKey.bytes,
+ Uint8List.fromList([1, 2, 3, 4, 5]),
+ );
+ });
+
+ test('handles returning empty list', () async {
+ mock
+ ..setGenerateKeyExpectations(bitsCount: 5)
+ ..setResponse(() => Uint8List(0));
+
+ await expectLater(
+ () => SecretKey.fromSecureRandom(5),
+ throwsA(
+ isA().having(
+ (e) => e.code,
+ 'code',
+ 'platform_returned_empty_data',
+ ),
+ ),
+ );
+ });
+
+ test('handles returning null', () async {
+ mock
+ ..setGenerateKeyExpectations(bitsCount: 5)
+ ..setResponse(() => null);
+
+ await expectLater(
+ () => SecretKey.fromSecureRandom(5),
+ throwsA(
+ isA().having(
+ (e) => e.code,
+ 'code',
+ 'platform_returned_null',
+ ),
+ ),
+ );
+ });
+
+ test('handles throwing PlatformException', () async {
+ mock
+ ..setGenerateKeyExpectations(bitsCount: 5)
+ ..setResponse(
+ () => throw PlatformException(
+ code: 'native_crypto',
+ message: 'dummy error',
+ ),
+ );
+
+ await expectLater(
+ () => SecretKey.fromSecureRandom(5),
+ throwsA(
+ isA()
+ .having(
+ (e) => e.message,
+ 'message',
+ 'PlatformException(native_crypto, dummy error, null, null)',
+ )
+ .having(
+ (e) => e.code,
+ 'code',
+ 'platform_throws',
+ ),
+ ),
+ );
+ });
+ });
+}
diff --git a/native_crypto_ios/example/.gitignore b/packages/native_crypto_android/.gitignore
similarity index 53%
rename from native_crypto_ios/example/.gitignore
rename to packages/native_crypto_android/.gitignore
index 0fa6b67..9be145f 100644
--- a/native_crypto_ios/example/.gitignore
+++ b/packages/native_crypto_android/.gitignore
@@ -21,26 +21,9 @@
#.vscode/
# Flutter/Dart/Pub related
+# Libraries should not include pubspec.lock, per https://dart.dev/guides/libraries/private-files#pubspeclock.
+/pubspec.lock
**/doc/api/
-**/ios/Flutter/.last_build_id
.dart_tool/
-.flutter-plugins
-.flutter-plugins-dependencies
.packages
-.pub-cache/
-.pub/
-/build/
-
-# Web related
-lib/generated_plugin_registrant.dart
-
-# Symbolication related
-app.*.symbols
-
-# Obfuscation related
-app.*.map.json
-
-# Android Studio will place build artifacts here
-/android/app/debug
-/android/app/profile
-/android/app/release
+build/
diff --git a/native_crypto_ios/example/.metadata b/packages/native_crypto_android/.metadata
similarity index 75%
rename from native_crypto_ios/example/.metadata
rename to packages/native_crypto_android/.metadata
index ee7f61d..8c15ad7 100644
--- a/native_crypto_ios/example/.metadata
+++ b/packages/native_crypto_android/.metadata
@@ -4,7 +4,7 @@
# This file should be version controlled and should not be manually edited.
version:
- revision: cf4400006550b70f28e4b4af815151d1e74846c6
+ revision: 77d935af4db863f6abd0b9c31c7e6df2a13de57b
channel: stable
-project_type: app
+project_type: plugin
diff --git a/packages/native_crypto_android/CHANGELOG.md b/packages/native_crypto_android/CHANGELOG.md
new file mode 100644
index 0000000..ce1055b
--- /dev/null
+++ b/packages/native_crypto_android/CHANGELOG.md
@@ -0,0 +1,41 @@
+## 0.1.1
+
+ - **REFACTOR**: clean and modernize kotlin code.
+ - **PERF**: x10 perfomance improvement on android with better list management.
+ - **FEAT**: export new exceptions.
+
+## 0.1.0
+
+> Breaking changes !
+
+* Follow **Federated Plugin** Flutter standard.
+
+## 0.0.6
+
+* Add KeyPair generation.
+* Rework exposed API.
+
+## 0.0.5
+
+* New API.
+* Add digest support.
+* Clean platform specific code base.
+
+## 0.0.4
+
+* Improve AES.
+
+## 0.0.3
+
+* Add PBKDF2 support.
+* Add exceptions.
+* Improve documentation.
+
+## 0.0.2
+
+* Add different key size support.
+* Improve performances.
+
+## 0.0.1
+
+* First AES cross-platform encryption & decryption implementation.
diff --git a/packages/native_crypto_android/LICENSE b/packages/native_crypto_android/LICENSE
new file mode 100644
index 0000000..dd5d33b
--- /dev/null
+++ b/packages/native_crypto_android/LICENSE
@@ -0,0 +1,23 @@
+NativeCrypto - Android Implementation
+
+MIT License
+
+Copyright (c) 2019 - 2022 Hugo Pointcheval
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.
\ No newline at end of file
diff --git a/native_crypto_ios/README.md b/packages/native_crypto_android/README.md
similarity index 94%
rename from native_crypto_ios/README.md
rename to packages/native_crypto_android/README.md
index 302c828..48b93a5 100644
--- a/native_crypto_ios/README.md
+++ b/packages/native_crypto_android/README.md
@@ -1,4 +1,4 @@
-# native_crypto_ios
+# native_crypto_android
A new flutter plugin project.
diff --git a/packages/native_crypto_android/android/.gitignore b/packages/native_crypto_android/android/.gitignore
new file mode 100644
index 0000000..c6cbe56
--- /dev/null
+++ b/packages/native_crypto_android/android/.gitignore
@@ -0,0 +1,8 @@
+*.iml
+.gradle
+/local.properties
+/.idea/workspace.xml
+/.idea/libraries
+.DS_Store
+/build
+/captures
diff --git a/packages/native_crypto_android/android/build.gradle b/packages/native_crypto_android/android/build.gradle
new file mode 100644
index 0000000..301735f
--- /dev/null
+++ b/packages/native_crypto_android/android/build.gradle
@@ -0,0 +1,50 @@
+group 'fr.pointcheval.native_crypto_android'
+version '1.0-SNAPSHOT'
+
+buildscript {
+ ext.kotlin_version = '1.6.21'
+ repositories {
+ google()
+ mavenCentral()
+ }
+
+ dependencies {
+ classpath 'com.android.tools.build:gradle:4.1.3'
+ classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
+ }
+}
+
+rootProject.allprojects {
+ repositories {
+ google()
+ mavenCentral()
+ }
+}
+
+apply plugin: 'com.android.library'
+apply plugin: 'kotlin-android'
+
+android {
+ compileSdkVersion 30
+
+ compileOptions {
+ sourceCompatibility JavaVersion.VERSION_1_8
+ targetCompatibility JavaVersion.VERSION_1_8
+ }
+
+ kotlinOptions {
+ jvmTarget = '1.8'
+ }
+
+ sourceSets {
+ main.java.srcDirs += 'src/main/kotlin'
+ }
+
+ defaultConfig {
+ minSdkVersion 26
+ }
+}
+
+dependencies {
+ implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version"
+}
diff --git a/packages/native_crypto_android/android/gradle/wrapper/gradle-wrapper.jar b/packages/native_crypto_android/android/gradle/wrapper/gradle-wrapper.jar
new file mode 100644
index 0000000..e708b1c
Binary files /dev/null and b/packages/native_crypto_android/android/gradle/wrapper/gradle-wrapper.jar differ
diff --git a/packages/native_crypto_android/android/gradle/wrapper/gradle-wrapper.properties b/packages/native_crypto_android/android/gradle/wrapper/gradle-wrapper.properties
new file mode 100644
index 0000000..da9702f
--- /dev/null
+++ b/packages/native_crypto_android/android/gradle/wrapper/gradle-wrapper.properties
@@ -0,0 +1,5 @@
+distributionBase=GRADLE_USER_HOME
+distributionPath=wrapper/dists
+distributionUrl=https\://services.gradle.org/distributions/gradle-6.8-bin.zip
+zipStoreBase=GRADLE_USER_HOME
+zipStorePath=wrapper/dists
diff --git a/packages/native_crypto_android/android/gradlew b/packages/native_crypto_android/android/gradlew
new file mode 100755
index 0000000..4f906e0
--- /dev/null
+++ b/packages/native_crypto_android/android/gradlew
@@ -0,0 +1,185 @@
+#!/usr/bin/env sh
+
+#
+# Copyright 2015 the original author or authors.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# https://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+
+##############################################################################
+##
+## Gradle start up script for UN*X
+##
+##############################################################################
+
+# Attempt to set APP_HOME
+# Resolve links: $0 may be a link
+PRG="$0"
+# Need this for relative symlinks.
+while [ -h "$PRG" ] ; do
+ ls=`ls -ld "$PRG"`
+ link=`expr "$ls" : '.*-> \(.*\)$'`
+ if expr "$link" : '/.*' > /dev/null; then
+ PRG="$link"
+ else
+ PRG=`dirname "$PRG"`"/$link"
+ fi
+done
+SAVED="`pwd`"
+cd "`dirname \"$PRG\"`/" >/dev/null
+APP_HOME="`pwd -P`"
+cd "$SAVED" >/dev/null
+
+APP_NAME="Gradle"
+APP_BASE_NAME=`basename "$0"`
+
+# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
+DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"'
+
+# Use the maximum available, or set MAX_FD != -1 to use that value.
+MAX_FD="maximum"
+
+warn () {
+ echo "$*"
+}
+
+die () {
+ echo
+ echo "$*"
+ echo
+ exit 1
+}
+
+# OS specific support (must be 'true' or 'false').
+cygwin=false
+msys=false
+darwin=false
+nonstop=false
+case "`uname`" in
+ CYGWIN* )
+ cygwin=true
+ ;;
+ Darwin* )
+ darwin=true
+ ;;
+ MINGW* )
+ msys=true
+ ;;
+ NONSTOP* )
+ nonstop=true
+ ;;
+esac
+
+CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
+
+
+# Determine the Java command to use to start the JVM.
+if [ -n "$JAVA_HOME" ] ; then
+ if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
+ # IBM's JDK on AIX uses strange locations for the executables
+ JAVACMD="$JAVA_HOME/jre/sh/java"
+ else
+ JAVACMD="$JAVA_HOME/bin/java"
+ fi
+ if [ ! -x "$JAVACMD" ] ; then
+ die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME
+
+Please set the JAVA_HOME variable in your environment to match the
+location of your Java installation."
+ fi
+else
+ JAVACMD="java"
+ which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
+
+Please set the JAVA_HOME variable in your environment to match the
+location of your Java installation."
+fi
+
+# Increase the maximum file descriptors if we can.
+if [ "$cygwin" = "false" -a "$darwin" = "false" -a "$nonstop" = "false" ] ; then
+ MAX_FD_LIMIT=`ulimit -H -n`
+ if [ $? -eq 0 ] ; then
+ if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then
+ MAX_FD="$MAX_FD_LIMIT"
+ fi
+ ulimit -n $MAX_FD
+ if [ $? -ne 0 ] ; then
+ warn "Could not set maximum file descriptor limit: $MAX_FD"
+ fi
+ else
+ warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT"
+ fi
+fi
+
+# For Darwin, add options to specify how the application appears in the dock
+if $darwin; then
+ GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\""
+fi
+
+# For Cygwin or MSYS, switch paths to Windows format before running java
+if [ "$cygwin" = "true" -o "$msys" = "true" ] ; then
+ APP_HOME=`cygpath --path --mixed "$APP_HOME"`
+ CLASSPATH=`cygpath --path --mixed "$CLASSPATH"`
+
+ JAVACMD=`cygpath --unix "$JAVACMD"`
+
+ # We build the pattern for arguments to be converted via cygpath
+ ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null`
+ SEP=""
+ for dir in $ROOTDIRSRAW ; do
+ ROOTDIRS="$ROOTDIRS$SEP$dir"
+ SEP="|"
+ done
+ OURCYGPATTERN="(^($ROOTDIRS))"
+ # Add a user-defined pattern to the cygpath arguments
+ if [ "$GRADLE_CYGPATTERN" != "" ] ; then
+ OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)"
+ fi
+ # Now convert the arguments - kludge to limit ourselves to /bin/sh
+ i=0
+ for arg in "$@" ; do
+ CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -`
+ CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option
+
+ if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition
+ eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"`
+ else
+ eval `echo args$i`="\"$arg\""
+ fi
+ i=`expr $i + 1`
+ done
+ case $i in
+ 0) set -- ;;
+ 1) set -- "$args0" ;;
+ 2) set -- "$args0" "$args1" ;;
+ 3) set -- "$args0" "$args1" "$args2" ;;
+ 4) set -- "$args0" "$args1" "$args2" "$args3" ;;
+ 5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;;
+ 6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;;
+ 7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;;
+ 8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;;
+ 9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;;
+ esac
+fi
+
+# Escape application args
+save () {
+ for i do printf %s\\n "$i" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/' \\\\/" ; done
+ echo " "
+}
+APP_ARGS=`save "$@"`
+
+# Collect all arguments for the java command, following the shell quoting and substitution rules
+eval set -- $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS "\"-Dorg.gradle.appname=$APP_BASE_NAME\"" -classpath "\"$CLASSPATH\"" org.gradle.wrapper.GradleWrapperMain "$APP_ARGS"
+
+exec "$JAVACMD" "$@"
diff --git a/packages/native_crypto_android/android/gradlew.bat b/packages/native_crypto_android/android/gradlew.bat
new file mode 100644
index 0000000..ac1b06f
--- /dev/null
+++ b/packages/native_crypto_android/android/gradlew.bat
@@ -0,0 +1,89 @@
+@rem
+@rem Copyright 2015 the original author or authors.
+@rem
+@rem Licensed under the Apache License, Version 2.0 (the "License");
+@rem you may not use this file except in compliance with the License.
+@rem You may obtain a copy of the License at
+@rem
+@rem https://www.apache.org/licenses/LICENSE-2.0
+@rem
+@rem Unless required by applicable law or agreed to in writing, software
+@rem distributed under the License is distributed on an "AS IS" BASIS,
+@rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+@rem See the License for the specific language governing permissions and
+@rem limitations under the License.
+@rem
+
+@if "%DEBUG%" == "" @echo off
+@rem ##########################################################################
+@rem
+@rem Gradle startup script for Windows
+@rem
+@rem ##########################################################################
+
+@rem Set local scope for the variables with windows NT shell
+if "%OS%"=="Windows_NT" setlocal
+
+set DIRNAME=%~dp0
+if "%DIRNAME%" == "" set DIRNAME=.
+set APP_BASE_NAME=%~n0
+set APP_HOME=%DIRNAME%
+
+@rem Resolve any "." and ".." in APP_HOME to make it shorter.
+for %%i in ("%APP_HOME%") do set APP_HOME=%%~fi
+
+@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
+set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m"
+
+@rem Find java.exe
+if defined JAVA_HOME goto findJavaFromJavaHome
+
+set JAVA_EXE=java.exe
+%JAVA_EXE% -version >NUL 2>&1
+if "%ERRORLEVEL%" == "0" goto execute
+
+echo.
+echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
+echo.
+echo Please set the JAVA_HOME variable in your environment to match the
+echo location of your Java installation.
+
+goto fail
+
+:findJavaFromJavaHome
+set JAVA_HOME=%JAVA_HOME:"=%
+set JAVA_EXE=%JAVA_HOME%/bin/java.exe
+
+if exist "%JAVA_EXE%" goto execute
+
+echo.
+echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%
+echo.
+echo Please set the JAVA_HOME variable in your environment to match the
+echo location of your Java installation.
+
+goto fail
+
+:execute
+@rem Setup the command line
+
+set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
+
+
+@rem Execute Gradle
+"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %*
+
+:end
+@rem End local scope for the variables with windows NT shell
+if "%ERRORLEVEL%"=="0" goto mainEnd
+
+:fail
+rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
+rem the _cmd.exe /c_ return code!
+if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1
+exit /b 1
+
+:mainEnd
+if "%OS%"=="Windows_NT" endlocal
+
+:omega
diff --git a/packages/native_crypto_android/android/settings.gradle b/packages/native_crypto_android/android/settings.gradle
new file mode 100644
index 0000000..3533b9f
--- /dev/null
+++ b/packages/native_crypto_android/android/settings.gradle
@@ -0,0 +1 @@
+rootProject.name = 'native_crypto_android'
diff --git a/packages/native_crypto_android/android/src/main/AndroidManifest.xml b/packages/native_crypto_android/android/src/main/AndroidManifest.xml
new file mode 100644
index 0000000..a750e9f
--- /dev/null
+++ b/packages/native_crypto_android/android/src/main/AndroidManifest.xml
@@ -0,0 +1,3 @@
+
+
diff --git a/packages/native_crypto_android/android/src/main/kotlin/fr/pointcheval/native_crypto_android/NativeCryptoAndroidPlugin.kt b/packages/native_crypto_android/android/src/main/kotlin/fr/pointcheval/native_crypto_android/NativeCryptoAndroidPlugin.kt
new file mode 100644
index 0000000..36cd412
--- /dev/null
+++ b/packages/native_crypto_android/android/src/main/kotlin/fr/pointcheval/native_crypto_android/NativeCryptoAndroidPlugin.kt
@@ -0,0 +1,160 @@
+package fr.pointcheval.native_crypto_android
+
+import androidx.annotation.NonNull
+import fr.pointcheval.native_crypto_android.interfaces.Cipher
+import fr.pointcheval.native_crypto_android.kdf.Pbkdf2
+import fr.pointcheval.native_crypto_android.keys.SecretKey
+import fr.pointcheval.native_crypto_android.utils.CipherAlgorithm
+import fr.pointcheval.native_crypto_android.utils.Constants
+import fr.pointcheval.native_crypto_android.utils.HashAlgorithm
+import fr.pointcheval.native_crypto_android.utils.Task
+import io.flutter.embedding.engine.plugins.FlutterPlugin
+import io.flutter.plugin.common.MethodCall
+import io.flutter.plugin.common.MethodChannel
+import io.flutter.plugin.common.MethodChannel.MethodCallHandler
+import io.flutter.plugin.common.MethodChannel.Result
+import java.util.*
+
+/** NativeCryptoAndroidPlugin */
+class NativeCryptoAndroidPlugin : FlutterPlugin, MethodCallHandler {
+ /// The MethodChannel that will the communication between Flutter and native Android
+ ///
+ /// This local reference serves to register the plugin with the Flutter Engine and unregister it
+ /// when the Flutter Engine is detached from the Activity
+ private lateinit var channel: MethodChannel
+ private val name = "plugins.hugop.cl/native_crypto"
+
+ private var cipherInstance: Cipher? = null
+
+ override fun onAttachedToEngine(@NonNull flutterPluginBinding: FlutterPlugin.FlutterPluginBinding) {
+ channel = MethodChannel(flutterPluginBinding.binaryMessenger, name)
+ channel.setMethodCallHandler(this)
+ }
+
+ override fun onDetachedFromEngine(@NonNull binding: FlutterPlugin.FlutterPluginBinding) {
+ channel.setMethodCallHandler(null)
+ }
+
+ override fun onMethodCall(@NonNull call: MethodCall, @NonNull result: Result) {
+ lateinit var methodCallTask: Task<*>
+
+ when (call.method) {
+ "digest" -> methodCallTask = handleDigest(call.arguments())
+ "generateSecretKey" -> methodCallTask = handleGenerateSecretKey(call.arguments())
+ "pbkdf2" -> methodCallTask = handlePbkdf2(call.arguments())
+ "encryptAsList" -> methodCallTask = handleEncryptAsList(call.arguments())
+ "decryptAsList" -> methodCallTask = handleDecryptAsList(call.arguments())
+ "encrypt" -> methodCallTask = handleCrypt(call.arguments(), true)
+ "decrypt" -> methodCallTask = handleCrypt(call.arguments(), false)
+ else -> result.notImplemented()
+ }
+
+ methodCallTask.call()
+
+ methodCallTask.finalize { task ->
+ if (task.isSuccessful()) {
+ result.success(task.getResult())
+ } else {
+ val exception: Exception = task.getException()
+ val message = exception.message
+ result.error("native_crypto", message, null)
+ }
+ }
+ }
+
+ private fun handleDigest(arguments: Map?): Task {
+ return Task {
+ val data: ByteArray =
+ Objects.requireNonNull(arguments?.get(Constants.DATA)) as ByteArray
+ val algorithm: String =
+ Objects.requireNonNull(arguments?.get(Constants.ALGORITHM)) as String
+ HashAlgorithm.digest(data, algorithm)
+ }
+ }
+
+ private fun handleGenerateSecretKey(arguments: Map?): Task {
+ return Task {
+ val bitsCount: Int = Objects.requireNonNull(arguments?.get(Constants.BITS_COUNT)) as Int
+ SecretKey.fromSecureRandom(bitsCount).bytes
+ }
+ }
+
+ private fun handlePbkdf2(arguments: Map?): Task {
+ return Task {
+ val password: String =
+ Objects.requireNonNull(arguments?.get(Constants.PASSWORD)) as String
+ val salt: String = Objects.requireNonNull(arguments?.get(Constants.SALT)) as String
+ val keyBytesCount: Int =
+ Objects.requireNonNull(arguments?.get(Constants.KEY_BYTES_COUNT)) as Int
+ val iterations: Int =
+ Objects.requireNonNull(arguments?.get(Constants.ITERATIONS)) as Int
+ val algorithm: String =
+ Objects.requireNonNull(arguments?.get(Constants.ALGORITHM)) as String
+
+ val pbkdf2: Pbkdf2 = Pbkdf2(keyBytesCount, iterations, HashAlgorithm.valueOf(algorithm))
+ pbkdf2.init(password, salt)
+
+ pbkdf2.derive().bytes
+ }
+ }
+
+ private fun lazyLoadCipher(cipherAlgorithm: CipherAlgorithm) {
+ if (cipherInstance == null) {
+ cipherInstance = cipherAlgorithm.getCipher()
+ } else {
+ if (cipherInstance!!.algorithm != cipherAlgorithm) {
+ cipherInstance = cipherAlgorithm.getCipher()
+ }
+ }
+ }
+
+ private fun handleEncryptAsList(arguments: Map?): Task> {
+ return Task {
+ val data: ByteArray =
+ Objects.requireNonNull(arguments?.get(Constants.DATA)) as ByteArray
+ val key: ByteArray = Objects.requireNonNull(arguments?.get(Constants.KEY)) as ByteArray
+ val algorithm: String =
+ Objects.requireNonNull(arguments?.get(Constants.ALGORITHM)) as String
+
+ val cipherAlgorithm: CipherAlgorithm = CipherAlgorithm.valueOf(algorithm)
+ lazyLoadCipher(cipherAlgorithm)
+
+ cipherInstance!!.encryptAsList(data, key)
+ }
+ }
+
+ private fun handleDecryptAsList(arguments: Map?): Task {
+ return Task {
+ val data: List =
+ Objects.requireNonNull(arguments?.get(Constants.DATA)) as List
+ val key: ByteArray = Objects.requireNonNull(arguments?.get(Constants.KEY)) as ByteArray
+ val algorithm: String =
+ Objects.requireNonNull(arguments?.get(Constants.ALGORITHM)) as String
+
+ val cipherAlgorithm: CipherAlgorithm = CipherAlgorithm.valueOf(algorithm)
+ lazyLoadCipher(cipherAlgorithm)
+
+ cipherInstance!!.decryptAsList(data, key)
+ }
+ }
+
+ // **EN**Crypt and **DE**Crypt
+ private fun handleCrypt(arguments: Map?, forEncryption: Boolean): Task {
+ return Task {
+ val data: ByteArray =
+ Objects.requireNonNull(arguments?.get(Constants.DATA)) as ByteArray
+ val key: ByteArray = Objects.requireNonNull(arguments?.get(Constants.KEY)) as ByteArray
+ val algorithm: String =
+ Objects.requireNonNull(arguments?.get(Constants.ALGORITHM)) as String
+
+ val cipherAlgorithm: CipherAlgorithm = CipherAlgorithm.valueOf(algorithm)
+ lazyLoadCipher(cipherAlgorithm)
+
+ if (forEncryption) {
+ cipherInstance!!.encrypt(data, key)
+ } else {
+ cipherInstance!!.decrypt(data, key)
+ }
+ }
+ }
+}
diff --git a/packages/native_crypto_android/android/src/main/kotlin/fr/pointcheval/native_crypto_android/ciphers/AES.kt b/packages/native_crypto_android/android/src/main/kotlin/fr/pointcheval/native_crypto_android/ciphers/AES.kt
new file mode 100644
index 0000000..0b4c86c
--- /dev/null
+++ b/packages/native_crypto_android/android/src/main/kotlin/fr/pointcheval/native_crypto_android/ciphers/AES.kt
@@ -0,0 +1,55 @@
+package fr.pointcheval.native_crypto_android.ciphers
+
+import fr.pointcheval.native_crypto_android.interfaces.Cipher
+import fr.pointcheval.native_crypto_android.utils.CipherAlgorithm
+import javax.crypto.SecretKey
+import javax.crypto.spec.GCMParameterSpec
+import javax.crypto.spec.IvParameterSpec
+import javax.crypto.spec.SecretKeySpec
+
+class AES : Cipher {
+ override val algorithm: CipherAlgorithm
+ get() = CipherAlgorithm.aes
+
+ var cipherInstance: javax.crypto.Cipher? = null;
+
+ fun lazyLoadCipher() {
+ if (cipherInstance == null) {
+ cipherInstance = javax.crypto.Cipher.getInstance("AES/GCM/NoPadding")
+ }
+ }
+
+ // native.crypto cipherText representation = [NONCE(12) || CIPHERTEXT(n-28) || TAG(16)]
+ // javax.crypto cipherText representation = [NONCE(12)] + [CIPHERTEXT(n-16) || TAG(16)]
+ override fun encrypt(data: ByteArray, key: ByteArray): ByteArray {
+ val list : List = encryptAsList(data, key)
+ return list.first().plus(list.last())
+ }
+
+ // native.crypto cipherText representation = [NONCE(12)] + [CIPHERTEXT(n-16) || TAG(16)]
+ // javax.crypto cipherText representation = [NONCE(12)] + [CIPHERTEXT(n-16) || TAG(16)]
+ override fun encryptAsList(data: ByteArray, key: ByteArray): List {
+ val sk = SecretKeySpec(key, "AES")
+ lazyLoadCipher()
+ cipherInstance!!.init(javax.crypto.Cipher.ENCRYPT_MODE, sk)
+ val bytes: ByteArray = cipherInstance!!.doFinal(data)
+ val iv: ByteArray = cipherInstance!!.iv
+ return listOf(iv, bytes)
+ }
+
+ override fun decrypt(data: ByteArray, key: ByteArray): ByteArray {
+ val iv: ByteArray = data.take(12).toByteArray()
+ val payload: ByteArray = data.drop(12).toByteArray()
+ return decryptAsList(listOf(iv, payload), key)
+ }
+
+ override fun decryptAsList(data: List, key: ByteArray): ByteArray {
+ val sk = SecretKeySpec(key, "AES")
+ val payload: ByteArray = data.last()
+ val iv: ByteArray = data.first()
+ val gcmSpec = GCMParameterSpec(16 * 8, iv)
+ lazyLoadCipher()
+ cipherInstance!!.init(javax.crypto.Cipher.DECRYPT_MODE, sk, gcmSpec)
+ return cipherInstance!!.doFinal(payload)
+ }
+}
\ No newline at end of file
diff --git a/packages/native_crypto_android/android/src/main/kotlin/fr/pointcheval/native_crypto_android/interfaces/Cipher.kt b/packages/native_crypto_android/android/src/main/kotlin/fr/pointcheval/native_crypto_android/interfaces/Cipher.kt
new file mode 100644
index 0000000..5893d25
--- /dev/null
+++ b/packages/native_crypto_android/android/src/main/kotlin/fr/pointcheval/native_crypto_android/interfaces/Cipher.kt
@@ -0,0 +1,12 @@
+package fr.pointcheval.native_crypto_android.interfaces
+
+import fr.pointcheval.native_crypto_android.utils.CipherAlgorithm
+
+interface Cipher {
+ val algorithm: CipherAlgorithm
+
+ fun encrypt(data: ByteArray, key: ByteArray): ByteArray
+ fun decrypt(data: ByteArray, key: ByteArray): ByteArray
+ fun encryptAsList(data: ByteArray, key: ByteArray): List
+ fun decryptAsList(data: List, key: ByteArray): ByteArray
+}
\ No newline at end of file
diff --git a/packages/native_crypto_android/android/src/main/kotlin/fr/pointcheval/native_crypto_android/interfaces/Key.kt b/packages/native_crypto_android/android/src/main/kotlin/fr/pointcheval/native_crypto_android/interfaces/Key.kt
new file mode 100644
index 0000000..4df212b
--- /dev/null
+++ b/packages/native_crypto_android/android/src/main/kotlin/fr/pointcheval/native_crypto_android/interfaces/Key.kt
@@ -0,0 +1,5 @@
+package fr.pointcheval.native_crypto_android.interfaces
+
+interface Key {
+ val bytes: ByteArray
+}
\ No newline at end of file
diff --git a/packages/native_crypto_android/android/src/main/kotlin/fr/pointcheval/native_crypto_android/interfaces/KeyDerivation.kt b/packages/native_crypto_android/android/src/main/kotlin/fr/pointcheval/native_crypto_android/interfaces/KeyDerivation.kt
new file mode 100644
index 0000000..6bd9216
--- /dev/null
+++ b/packages/native_crypto_android/android/src/main/kotlin/fr/pointcheval/native_crypto_android/interfaces/KeyDerivation.kt
@@ -0,0 +1,10 @@
+package fr.pointcheval.native_crypto_android.interfaces
+
+import fr.pointcheval.native_crypto_android.keys.SecretKey
+import fr.pointcheval.native_crypto_android.utils.KdfAlgorithm
+
+interface KeyDerivation {
+ val algorithm: KdfAlgorithm
+
+ fun derive(): SecretKey
+}
\ No newline at end of file
diff --git a/packages/native_crypto_android/android/src/main/kotlin/fr/pointcheval/native_crypto_android/kdf/Pbkdf2.kt b/packages/native_crypto_android/android/src/main/kotlin/fr/pointcheval/native_crypto_android/kdf/Pbkdf2.kt
new file mode 100644
index 0000000..17d8c5e
--- /dev/null
+++ b/packages/native_crypto_android/android/src/main/kotlin/fr/pointcheval/native_crypto_android/kdf/Pbkdf2.kt
@@ -0,0 +1,39 @@
+package fr.pointcheval.native_crypto_android.kdf
+
+import fr.pointcheval.native_crypto_android.interfaces.KeyDerivation
+import fr.pointcheval.native_crypto_android.keys.SecretKey
+import fr.pointcheval.native_crypto_android.utils.HashAlgorithm
+import fr.pointcheval.native_crypto_android.utils.KdfAlgorithm
+import javax.crypto.SecretKeyFactory
+import javax.crypto.spec.PBEKeySpec
+
+class Pbkdf2(
+ private val keyBytesCount: Int, private val iterations: Int,
+ private val hash: HashAlgorithm = HashAlgorithm.sha256
+) : KeyDerivation {
+
+ private var password: String? = null
+ private var salt: String? = null
+
+ fun init(password: String, salt: String) {
+ this.password = password
+ this.salt = salt
+ }
+
+ override val algorithm: KdfAlgorithm
+ get() = KdfAlgorithm.pbkdf2
+
+ override fun derive(): SecretKey {
+ if (password == null || salt == null) {
+ throw Exception("Password and Salt must be initialized.")
+ }
+ val spec = PBEKeySpec(
+ password!!.toCharArray(),
+ salt!!.toByteArray(),
+ iterations,
+ keyBytesCount * 8
+ )
+ val skf: SecretKeyFactory = SecretKeyFactory.getInstance(hash.pbkdf2String())
+ return SecretKey(skf.generateSecret(spec).encoded)
+ }
+}
\ No newline at end of file
diff --git a/packages/native_crypto_android/android/src/main/kotlin/fr/pointcheval/native_crypto_android/keys/SecretKey.kt b/packages/native_crypto_android/android/src/main/kotlin/fr/pointcheval/native_crypto_android/keys/SecretKey.kt
new file mode 100644
index 0000000..07e9833
--- /dev/null
+++ b/packages/native_crypto_android/android/src/main/kotlin/fr/pointcheval/native_crypto_android/keys/SecretKey.kt
@@ -0,0 +1,14 @@
+package fr.pointcheval.native_crypto_android.keys
+
+import fr.pointcheval.native_crypto_android.interfaces.Key
+import java.security.SecureRandom
+
+class SecretKey(override val bytes: ByteArray) : Key {
+ companion object {
+ fun fromSecureRandom(bitsCount: Int): SecretKey {
+ val bytes = ByteArray(bitsCount / 8)
+ SecureRandom.getInstanceStrong().nextBytes(bytes)
+ return SecretKey(bytes)
+ }
+ }
+}
\ No newline at end of file
diff --git a/packages/native_crypto_android/android/src/main/kotlin/fr/pointcheval/native_crypto_android/utils/CipherAlgorithm.kt b/packages/native_crypto_android/android/src/main/kotlin/fr/pointcheval/native_crypto_android/utils/CipherAlgorithm.kt
new file mode 100644
index 0000000..a95185f
--- /dev/null
+++ b/packages/native_crypto_android/android/src/main/kotlin/fr/pointcheval/native_crypto_android/utils/CipherAlgorithm.kt
@@ -0,0 +1,14 @@
+package fr.pointcheval.native_crypto_android.utils
+
+import fr.pointcheval.native_crypto_android.ciphers.AES
+import fr.pointcheval.native_crypto_android.interfaces.Cipher
+
+enum class CipherAlgorithm {
+ aes;
+
+ fun getCipher(): Cipher {
+ return when (this) {
+ aes -> AES()
+ }
+ }
+}
\ No newline at end of file
diff --git a/packages/native_crypto_android/android/src/main/kotlin/fr/pointcheval/native_crypto_android/utils/Constants.kt b/packages/native_crypto_android/android/src/main/kotlin/fr/pointcheval/native_crypto_android/utils/Constants.kt
new file mode 100644
index 0000000..1cb359a
--- /dev/null
+++ b/packages/native_crypto_android/android/src/main/kotlin/fr/pointcheval/native_crypto_android/utils/Constants.kt
@@ -0,0 +1,14 @@
+package fr.pointcheval.native_crypto_android.utils
+
+object Constants {
+ const val ALGORITHM = "algorithm"
+ const val BITS_COUNT = "bitsCount"
+ const val DATA = "data"
+ const val PASSWORD = "password"
+ const val SALT = "salt"
+ const val KEY = "key"
+ const val KEY_BYTES_COUNT = "keyBytesCount"
+ const val ITERATIONS = "iterations"
+ const val EPHEMERAL_PRIVATE_KEY = "ephemeralPrivateKey"
+ const val OTHER_PUBLIC_KEY = "otherPublicKey"
+}
\ No newline at end of file
diff --git a/packages/native_crypto_android/android/src/main/kotlin/fr/pointcheval/native_crypto_android/utils/HashAlgorithm.kt b/packages/native_crypto_android/android/src/main/kotlin/fr/pointcheval/native_crypto_android/utils/HashAlgorithm.kt
new file mode 100644
index 0000000..904f7ce
--- /dev/null
+++ b/packages/native_crypto_android/android/src/main/kotlin/fr/pointcheval/native_crypto_android/utils/HashAlgorithm.kt
@@ -0,0 +1,50 @@
+package fr.pointcheval.native_crypto_android.utils
+
+import java.security.MessageDigest
+
+@Suppress("EnumEntryName")
+enum class HashAlgorithm(val bitsCount: Int) {
+ sha256(256),
+ sha384(384),
+ sha512(512);
+
+ fun messageDigestString(): String {
+ return when (this) {
+ sha256 -> "SHA-256"
+ sha384 -> "SHA-384"
+ sha512 -> "SHA-512"
+ }
+ }
+
+ fun hmacString(): String {
+ return when (this) {
+ sha256 -> "HmacSHA256"
+ sha384 -> "HmacSHA384"
+ sha512 -> "HmacSHA512"
+ }
+ }
+
+ fun pbkdf2String(): String {
+ return when (this) {
+ sha256 -> "PBKDF2WithHmacSHA256"
+ sha384 -> "PBKDF2WithHmacSHA384"
+ sha512 -> "PBKDF2WithHmacSHA512"
+ }
+ }
+
+ fun digest(data: ByteArray): ByteArray {
+ val md = MessageDigest.getInstance(messageDigestString())
+ return md.digest(data)
+ }
+
+ companion object {
+ fun digest(data: ByteArray, algorithm: String): ByteArray {
+ for (h in values()) {
+ if (h.name == algorithm) {
+ return h.digest(data)
+ }
+ }
+ throw Exception("Unknown HashAlgorithm: $algorithm")
+ }
+ }
+}
\ No newline at end of file
diff --git a/packages/native_crypto_android/android/src/main/kotlin/fr/pointcheval/native_crypto_android/utils/KdfAlgorithm.kt b/packages/native_crypto_android/android/src/main/kotlin/fr/pointcheval/native_crypto_android/utils/KdfAlgorithm.kt
new file mode 100644
index 0000000..4ef9f69
--- /dev/null
+++ b/packages/native_crypto_android/android/src/main/kotlin/fr/pointcheval/native_crypto_android/utils/KdfAlgorithm.kt
@@ -0,0 +1,5 @@
+package fr.pointcheval.native_crypto_android.utils
+
+enum class KdfAlgorithm {
+ pbkdf2
+}
\ No newline at end of file
diff --git a/packages/native_crypto_android/android/src/main/kotlin/fr/pointcheval/native_crypto_android/utils/Task.kt b/packages/native_crypto_android/android/src/main/kotlin/fr/pointcheval/native_crypto_android/utils/Task.kt
new file mode 100644
index 0000000..d4832de
--- /dev/null
+++ b/packages/native_crypto_android/android/src/main/kotlin/fr/pointcheval/native_crypto_android/utils/Task.kt
@@ -0,0 +1,44 @@
+package fr.pointcheval.native_crypto_android.utils
+
+class Task(private var task: () -> T) {
+
+ private var successful = false
+ private var result: T? = null
+ private var exception: Exception? = null
+
+ fun isSuccessful(): Boolean {
+ return successful
+ }
+
+ fun getResult(): T {
+ if (successful && result != null) {
+ return result!!
+ } else {
+ throw Exception("No result found!")
+ }
+ }
+
+ fun getException(): Exception {
+ if (exception != null) {
+ return exception!!
+ } else {
+ throw Exception("No exception found!")
+ }
+ }
+
+ fun call() {
+ try {
+ result = task()
+ exception = null
+ successful = true
+ } catch (e: Exception) {
+ exception = e
+ result = null
+ successful = false
+ }
+ }
+
+ fun finalize(callback: (task: Task) -> Unit) {
+ callback(this)
+ }
+}
\ No newline at end of file
diff --git a/packages/native_crypto_android/pubspec.yaml b/packages/native_crypto_android/pubspec.yaml
new file mode 100644
index 0000000..8b40a04
--- /dev/null
+++ b/packages/native_crypto_android/pubspec.yaml
@@ -0,0 +1,23 @@
+name: native_crypto_android
+description: Android implementation of NativeCrypto
+version: 0.1.1
+
+environment:
+ sdk: ">=2.15.1 <3.0.0"
+ flutter: ">=2.5.0"
+
+dependencies:
+ flutter:
+ sdk: flutter
+
+dev_dependencies:
+ flutter_test:
+ sdk: flutter
+
+flutter:
+ plugin:
+ implements: native_crypto
+ platforms:
+ android:
+ package: fr.pointcheval.native_crypto_android
+ pluginClass: NativeCryptoAndroidPlugin
\ No newline at end of file
diff --git a/native_crypto_ios/.gitignore b/packages/native_crypto_ios/.gitignore
similarity index 100%
rename from native_crypto_ios/.gitignore
rename to packages/native_crypto_ios/.gitignore
diff --git a/native_crypto_ios/.metadata b/packages/native_crypto_ios/.metadata
similarity index 100%
rename from native_crypto_ios/.metadata
rename to packages/native_crypto_ios/.metadata
diff --git a/packages/native_crypto_ios/CHANGELOG.md b/packages/native_crypto_ios/CHANGELOG.md
new file mode 100644
index 0000000..1511feb
--- /dev/null
+++ b/packages/native_crypto_ios/CHANGELOG.md
@@ -0,0 +1,40 @@
+## 0.1.1
+
+ - **REFACTOR**: rework swift part.
+ - **PERF**: optimize swift code.
+
+## 0.1.0
+
+> Breaking changes !
+
+* Follow **Federated Plugin** Flutter standard.
+
+## 0.0.6
+
+* Add KeyPair generation.
+* Rework exposed API.
+
+## 0.0.5
+
+* New API.
+* Add digest support.
+* Clean platform specific code base.
+
+## 0.0.4
+
+* Improve AES.
+
+## 0.0.3
+
+* Add PBKDF2 support.
+* Add exceptions.
+* Improve documentation.
+
+## 0.0.2
+
+* Add different key size support.
+* Improve performances.
+
+## 0.0.1
+
+* First AES cross-platform encryption & decryption implementation.
diff --git a/native_crypto_ios/LICENSE b/packages/native_crypto_ios/LICENSE
similarity index 96%
rename from native_crypto_ios/LICENSE
rename to packages/native_crypto_ios/LICENSE
index a9f90ec..8c5c1f7 100644
--- a/native_crypto_ios/LICENSE
+++ b/packages/native_crypto_ios/LICENSE
@@ -2,7 +2,7 @@ NativeCrypto - iOS Implementation
MIT License
-Copyright (c) 2021 Hugo Pointcheval
+Copyright (c) 2019 - 2022 Hugo Pointcheval
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
diff --git a/packages/native_crypto_ios/README.md b/packages/native_crypto_ios/README.md
new file mode 100644
index 0000000..a60dd49
--- /dev/null
+++ b/packages/native_crypto_ios/README.md
@@ -0,0 +1,15 @@
+# NativeCrypto - iOS Implementation
+
+iOS Implementation of NativeCrypto Plugin.
+
+## Getting Started
+
+This project is a starting point for a Flutter
+[plug-in package](https://flutter.dev/developing-packages/),
+a specialized package that includes platform-specific implementation code for
+Android and/or iOS.
+
+For help getting started with Flutter, view our
+[online documentation](https://flutter.dev/docs), which offers tutorials,
+samples, guidance on mobile development, and a full API reference.
+
diff --git a/native_crypto_ios/ios/.gitignore b/packages/native_crypto_ios/ios/.gitignore
similarity index 100%
rename from native_crypto_ios/ios/.gitignore
rename to packages/native_crypto_ios/ios/.gitignore
diff --git a/native_crypto_ios/ios/Assets/.gitkeep b/packages/native_crypto_ios/ios/Assets/.gitkeep
similarity index 100%
rename from native_crypto_ios/ios/Assets/.gitkeep
rename to packages/native_crypto_ios/ios/Assets/.gitkeep
diff --git a/native_crypto_ios/ios/Classes/NativeCryptoIosPlugin.h b/packages/native_crypto_ios/ios/Classes/NativeCryptoIosPlugin.h
similarity index 100%
rename from native_crypto_ios/ios/Classes/NativeCryptoIosPlugin.h
rename to packages/native_crypto_ios/ios/Classes/NativeCryptoIosPlugin.h
diff --git a/native_crypto_ios/ios/Classes/NativeCryptoIosPlugin.m b/packages/native_crypto_ios/ios/Classes/NativeCryptoIosPlugin.m
similarity index 100%
rename from native_crypto_ios/ios/Classes/NativeCryptoIosPlugin.m
rename to packages/native_crypto_ios/ios/Classes/NativeCryptoIosPlugin.m
diff --git a/packages/native_crypto_ios/ios/Classes/SwiftNativeCryptoIosPlugin.swift b/packages/native_crypto_ios/ios/Classes/SwiftNativeCryptoIosPlugin.swift
new file mode 100644
index 0000000..c9b1a84
--- /dev/null
+++ b/packages/native_crypto_ios/ios/Classes/SwiftNativeCryptoIosPlugin.swift
@@ -0,0 +1,146 @@
+import Flutter
+import UIKit
+
+@available(iOS 13.0, *)
+public class SwiftNativeCryptoIosPlugin: NSObject, FlutterPlugin {
+ static let name: String = "plugins.hugop.cl/native_crypto"
+
+ public static func register(with registrar: FlutterPluginRegistrar) {
+ let channel = FlutterMethodChannel(name: name, binaryMessenger: registrar.messenger())
+ let instance = SwiftNativeCryptoIosPlugin()
+ registrar.addMethodCallDelegate(instance, channel: channel)
+ }
+
+ public func handle(_ call: FlutterMethodCall, result: @escaping FlutterResult) {
+ switch call.method {
+ case "digest": _call(task: handleDigest(call: call), result: result)
+ case "generateSecretKey": _call(task: handleGenerateSecretKey(call: call), result: result)
+ case "pbkdf2": _call(task: handlePbkdf2(call: call), result: result)
+ case "encryptAsList": _call(task: handleEncryptAsList(call: call), result: result)
+ case "decryptAsList": _call(task: handleDecryptAsList(call: call), result: result)
+ case "encrypt": _call(task: handleCrypt(call: call, forEncryption: true), result: result)
+ case "decrypt": _call(task: handleCrypt(call: call, forEncryption: false), result: result)
+ default: result(FlutterMethodNotImplemented)
+ }
+ }
+
+ private func _call(task: Task, result: @escaping FlutterResult) {
+ task.call()
+ task.finalize(callback: {(task: Task) in
+ if (task.isSuccessful()) {
+ result(task.getResult()!)
+ } else {
+ let exception: Error = task.getException()
+ let message = exception.localizedDescription
+ result(FlutterError(code: "native_crypto", message: message, details: nil))
+ }
+ })
+ }
+
+ private func handleDigest(call: FlutterMethodCall) -> Task {
+ return Task(task: {
+ let args : NSDictionary = call.arguments as! NSDictionary
+
+ let data : Data = (args["data"] as! FlutterStandardTypedData).data
+ let algorithm : String = args["algorithm"] as! String
+
+ return FlutterStandardTypedData.init(bytes: try HashAlgorithm.digest(data: data, algorithm: algorithm))
+ })
+ }
+
+ private func handleGenerateSecretKey(call: FlutterMethodCall) -> Task {
+ return Task(task: {
+ let args : NSDictionary = call.arguments as! NSDictionary
+
+ let bitsCount : NSNumber = args["bitsCount"] as! NSNumber
+
+ return FlutterStandardTypedData.init(bytes: SecretKey(fromSecureRandom: bitsCount.intValue).bytes)
+ })
+ }
+
+ private func handlePbkdf2(call: FlutterMethodCall) -> Task {
+ return Task(task: {
+ let args : NSDictionary = call.arguments as! NSDictionary
+
+ let password : String = args["password"] as! String
+ let salt : String = args["salt"] as! String
+ let keyBytesCount : NSNumber = args["keyBytesCount"] as! NSNumber
+ let iterations : NSNumber = args["iterations"] as! NSNumber
+ let algorithm : String = args["algorithm"] as! String
+
+ let pbkdf2 : Pbkdf2 = Pbkdf2(keyBytesCount: keyBytesCount.intValue, iterations: iterations.intValue)
+ pbkdf2.hash = HashAlgorithm.init(rawValue: algorithm) ?? pbkdf2.hash
+ pbkdf2.initialize(password: password, salt: salt)
+
+ return FlutterStandardTypedData.init(bytes: try pbkdf2.derive().bytes)
+ })
+ }
+
+ private func handleEncryptAsList(call: FlutterMethodCall) -> Task> {
+ return Task(task: {
+ let args : NSDictionary = call.arguments as! NSDictionary
+
+ let data : Data = (args["data"] as! FlutterStandardTypedData).data
+ let key : Data = (args["key"] as! FlutterStandardTypedData).data
+ let algorithm : String = args["algorithm"] as! String
+
+ let cipherAlgorithm : CipherAlgorithm? = CipherAlgorithm.init(rawValue: algorithm)
+ var cipher : Cipher
+ if (cipherAlgorithm != nil) {
+ cipher = cipherAlgorithm!.getCipher
+ } else {
+ throw NativeCryptoError.cipherError
+ }
+
+ return try cipher.encryptAsList(data: data, key: key)
+ })
+ }
+
+ private func handleDecryptAsList(call: FlutterMethodCall) -> Task {
+ return Task(task: {
+ let args : NSDictionary = call.arguments as! NSDictionary
+
+ let data = args["data"] as! NSArray
+ let key : Data = (args["key"] as! FlutterStandardTypedData).data
+ let algorithm : String = args["algorithm"] as! String
+
+ let iv = (data[0] as! FlutterStandardTypedData).data
+ let encrypted = (data[1] as! FlutterStandardTypedData).data
+
+ let cipherAlgorithm : CipherAlgorithm? = CipherAlgorithm.init(rawValue: algorithm)
+ var cipher : Cipher
+ if (cipherAlgorithm != nil) {
+ cipher = cipherAlgorithm!.getCipher
+ } else {
+ throw NativeCryptoError.cipherError
+ }
+
+ return FlutterStandardTypedData.init(bytes: try cipher.decryptAsList(data: [iv, encrypted], key: key))
+ })
+ }
+
+ private func handleCrypt(call: FlutterMethodCall, forEncryption: Bool) -> Task {
+ return Task(task: {
+ let args : NSDictionary = call.arguments as! NSDictionary
+
+ let data : Data = (args["data"] as! FlutterStandardTypedData).data
+ let key : Data = (args["key"] as! FlutterStandardTypedData).data
+ let algorithm : String = args["algorithm"] as! String
+
+ let cipherAlgorithm : CipherAlgorithm? = CipherAlgorithm.init(rawValue: algorithm)
+ var cipher : Cipher
+ if (cipherAlgorithm != nil) {
+ cipher = cipherAlgorithm!.getCipher
+ } else {
+ throw NativeCryptoError.cipherError
+ }
+
+ if (forEncryption) {
+ return FlutterStandardTypedData.init(bytes: try cipher.encrypt(data: data, key: key))
+ } else {
+ return FlutterStandardTypedData.init(bytes: try cipher.decrypt(data: data, key: key))
+ }
+ })
+ }
+
+}
diff --git a/packages/native_crypto_ios/ios/Classes/ciphers/AESCipher.swift b/packages/native_crypto_ios/ios/Classes/ciphers/AESCipher.swift
new file mode 100644
index 0000000..2110ff5
--- /dev/null
+++ b/packages/native_crypto_ios/ios/Classes/ciphers/AESCipher.swift
@@ -0,0 +1,57 @@
+//
+// AESCipher.swift
+// native_crypto_ios
+//
+// Created by Hugo Pointcheval on 25/05/2022.
+//
+
+import Foundation
+import CryptoKit
+
+class AESCipher : Cipher {
+ var algorithm: CipherAlgorithm = CipherAlgorithm.aes
+
+ /// Encrypts plaintext with key using AES GCM
+ @available(iOS 13.0, *)
+ func encrypt(data: Data, key: Data) throws -> Data {
+ let symmetricKey : SymmetricKey = SymmetricKey.init(data: key)
+ let encrypted : AES.GCM.SealedBox? = try? AES.GCM.seal(data, using: symmetricKey)
+
+ let encryptedData : Data? = encrypted?.combined
+ if (encryptedData == nil) {
+ throw NativeCryptoError.encryptionError
+ }
+ return encryptedData!
+ }
+
+ /// Decrypts ciphertext with key using AES GCM
+ @available(iOS 13.0, *)
+ func decrypt(data: Data, key: Data) throws -> Data {
+ let symmetricKey = SymmetricKey.init(data: key)
+ let sealedBox = try? AES.GCM.SealedBox(combined: data)
+ if (sealedBox == nil) { return Data.init() }
+ let decryptedData = try? AES.GCM.open(sealedBox!, using: symmetricKey)
+ if (decryptedData == nil) {
+ throw NativeCryptoError.decryptionError
+ }
+ return decryptedData!
+ }
+
+ func encryptAsList(data: Data, key: Data) throws -> [Data] {
+ let encryptedData = try encrypt(data: data, key: key)
+
+ let iv = encryptedData.prefix(12)
+ let data = encryptedData.suffix(from: 12)
+
+ return [iv, data]
+ }
+
+ func decryptAsList(data: [Data], key: Data) throws -> Data {
+ var encryptedData = data.first!
+ let data = data.last!
+ encryptedData.append(data)
+
+ let decryptedData = try decrypt(data: encryptedData, key: key)
+ return decryptedData
+ }
+}
diff --git a/packages/native_crypto_ios/ios/Classes/kdf/Pbkdf2.swift b/packages/native_crypto_ios/ios/Classes/kdf/Pbkdf2.swift
new file mode 100644
index 0000000..8a34a1e
--- /dev/null
+++ b/packages/native_crypto_ios/ios/Classes/kdf/Pbkdf2.swift
@@ -0,0 +1,63 @@
+//
+// Pbkdf2.swift
+// native_crypto_ios
+//
+// Created by Hugo Pointcheval on 25/05/2022.
+//
+
+import Foundation
+import CommonCrypto
+
+class Pbkdf2 : KeyDerivation {
+ var algorithm: KdfAlgorithm = KdfAlgorithm.pbkdf2
+
+ var keyBytesCount: Int
+ var iterations: Int
+ var hash: HashAlgorithm = HashAlgorithm.HashSHA256
+
+ var password: String? = nil
+ var salt: String? = nil
+
+ init(keyBytesCount: Int, iterations: Int) {
+ self.keyBytesCount = keyBytesCount
+ self.iterations = iterations
+ }
+
+ func initialize(password: String, salt: String) {
+ self.password = password
+ self.salt = salt
+ }
+
+ func derive() throws -> SecretKey {
+ if (password == nil || salt == nil) {
+ throw NativeCryptoError.pbkdf2Error
+ }
+
+ let passwordData = password!.data(using: .utf8)!
+ let saltData = salt!.data(using: .utf8)!
+
+ var derivedKeyData = Data(repeating: 0, count: keyBytesCount)
+ let localDerivedKeyData = derivedKeyData
+
+ let status = derivedKeyData.withUnsafeMutableBytes { (derivedKeyBytes: UnsafeMutableRawBufferPointer) in
+ saltData.withUnsafeBytes { (saltBytes: UnsafeRawBufferPointer) in
+ CCKeyDerivationPBKDF(
+ CCPBKDFAlgorithm(kCCPBKDF2),
+ password,
+ passwordData.count,
+ saltBytes.bindMemory(to: UInt8.self).baseAddress,
+ saltData.count,
+ hash.pbkdf2identifier,
+ UInt32(iterations),
+ derivedKeyBytes.bindMemory(to: UInt8.self).baseAddress,
+ localDerivedKeyData.count)
+ }
+ }
+
+ if (status != kCCSuccess) {
+ throw NativeCryptoError.pbkdf2Error
+ }
+
+ return SecretKey(derivedKeyData)
+ }
+}
diff --git a/packages/native_crypto_ios/ios/Classes/keys/SecretKey.swift b/packages/native_crypto_ios/ios/Classes/keys/SecretKey.swift
new file mode 100644
index 0000000..6325143
--- /dev/null
+++ b/packages/native_crypto_ios/ios/Classes/keys/SecretKey.swift
@@ -0,0 +1,25 @@
+//
+// SecretKey.swift
+// native_crypto_ios
+//
+// Created by Hugo Pointcheval on 25/05/2022.
+//
+
+import Foundation
+import CryptoKit
+
+class SecretKey : Key {
+ var bytes: Data
+
+ init(_ bytes: Data) {
+ self.bytes = bytes
+ }
+
+ init(fromSecureRandom bitsCount: Int) {
+ let symmetricKey = SymmetricKey.init(size: SymmetricKeySize(bitCount: bitsCount))
+ bytes = symmetricKey.withUnsafeBytes
+ {
+ return Data(Array($0))
+ }
+ }
+}
diff --git a/packages/native_crypto_ios/ios/Classes/protocols/Cipher.swift b/packages/native_crypto_ios/ios/Classes/protocols/Cipher.swift
new file mode 100644
index 0000000..f1291f9
--- /dev/null
+++ b/packages/native_crypto_ios/ios/Classes/protocols/Cipher.swift
@@ -0,0 +1,16 @@
+//
+// Cipher.swift
+// native_crypto_ios
+//
+// Created by Hugo Pointcheval on 25/05/2022.
+//
+
+import Foundation
+
+protocol Cipher {
+ var algorithm: CipherAlgorithm { get }
+ func encrypt(data: Data, key: Data) throws -> Data
+ func decrypt(data: Data, key: Data) throws -> Data
+ func encryptAsList(data: Data, key: Data) throws -> [Data]
+ func decryptAsList(data: [Data], key: Data) throws-> Data
+}
diff --git a/packages/native_crypto_ios/ios/Classes/protocols/Key.swift b/packages/native_crypto_ios/ios/Classes/protocols/Key.swift
new file mode 100644
index 0000000..9fc9199
--- /dev/null
+++ b/packages/native_crypto_ios/ios/Classes/protocols/Key.swift
@@ -0,0 +1,12 @@
+//
+// Key.swift
+// native_crypto_ios
+//
+// Created by Hugo Pointcheval on 25/05/2022.
+//
+
+import Foundation
+
+protocol Key {
+ var bytes: Data { get set }
+}
diff --git a/packages/native_crypto_ios/ios/Classes/protocols/KeyDerivation.swift b/packages/native_crypto_ios/ios/Classes/protocols/KeyDerivation.swift
new file mode 100644
index 0000000..df3a0d5
--- /dev/null
+++ b/packages/native_crypto_ios/ios/Classes/protocols/KeyDerivation.swift
@@ -0,0 +1,13 @@
+//
+// KeyDerivation.swift
+// native_crypto_ios
+//
+// Created by Hugo Pointcheval on 25/05/2022.
+//
+
+import Foundation
+
+protocol KeyDerivation {
+ var algorithm : KdfAlgorithm { get }
+ func derive() throws -> SecretKey
+}
diff --git a/packages/native_crypto_ios/ios/Classes/utils/CipherAlgorithm.swift b/packages/native_crypto_ios/ios/Classes/utils/CipherAlgorithm.swift
new file mode 100644
index 0000000..afb9094
--- /dev/null
+++ b/packages/native_crypto_ios/ios/Classes/utils/CipherAlgorithm.swift
@@ -0,0 +1,18 @@
+//
+// CipherAlgorithm.swift
+// native_crypto_ios
+//
+// Created by Hugo Pointcheval on 25/05/2022.
+//
+
+import Foundation
+
+enum CipherAlgorithm : String {
+ case aes = "aes"
+
+ var getCipher: Cipher {
+ switch self {
+ case .aes: return AESCipher()
+ }
+ }
+}
diff --git a/packages/native_crypto_ios/ios/Classes/utils/HashAlgorithm.swift b/packages/native_crypto_ios/ios/Classes/utils/HashAlgorithm.swift
new file mode 100644
index 0000000..38b7740
--- /dev/null
+++ b/packages/native_crypto_ios/ios/Classes/utils/HashAlgorithm.swift
@@ -0,0 +1,45 @@
+//
+// HashAlgorithm.swift
+// native_crypto_ios
+//
+// Created by Hugo Pointcheval on 25/05/2022.
+//
+
+import Foundation
+import CommonCrypto
+import CryptoKit
+
+enum HashAlgorithm: String {
+ case HashSHA256 = "sha256"
+ case HashSHA384 = "sha384"
+ case HashSHA512 = "sha512"
+
+ var pbkdf2identifier: UInt32 {
+ switch self {
+ case .HashSHA256: return CCPBKDFAlgorithm(kCCPRFHmacAlgSHA256)
+ case .HashSHA384: return CCPBKDFAlgorithm(kCCPRFHmacAlgSHA384)
+ case .HashSHA512: return CCPBKDFAlgorithm(kCCPRFHmacAlgSHA512)
+ }
+ }
+
+ @available(iOS 13.0, *)
+ func digest(data: Data) -> Data {
+ switch self {
+ case .HashSHA256:
+ return Data(SHA256.hash(data: data))
+ case .HashSHA384:
+ return Data(SHA384.hash(data: data))
+ case .HashSHA512:
+ return Data(SHA512.hash(data: data))
+ }
+ }
+
+ @available(iOS 13.0, *)
+ static func digest(data: Data, algorithm: String) throws -> Data {
+ let algo = HashAlgorithm.init(rawValue: algorithm)
+ if (algo == nil) {
+ throw NativeCryptoError.messageDigestError
+ }
+ return algo!.digest(data: data)
+ }
+}
diff --git a/packages/native_crypto_ios/ios/Classes/utils/KdfAlgorithm.swift b/packages/native_crypto_ios/ios/Classes/utils/KdfAlgorithm.swift
new file mode 100644
index 0000000..d6af3c1
--- /dev/null
+++ b/packages/native_crypto_ios/ios/Classes/utils/KdfAlgorithm.swift
@@ -0,0 +1,12 @@
+//
+// KdfAlgorithm.swift
+// native_crypto_ios
+//
+// Created by Hugo Pointcheval on 25/05/2022.
+//
+
+import Foundation
+
+enum KdfAlgorithm {
+ case pbkdf2
+}
diff --git a/packages/native_crypto_ios/ios/Classes/utils/NativeCryptoError.swift b/packages/native_crypto_ios/ios/Classes/utils/NativeCryptoError.swift
new file mode 100644
index 0000000..a2ac159
--- /dev/null
+++ b/packages/native_crypto_ios/ios/Classes/utils/NativeCryptoError.swift
@@ -0,0 +1,18 @@
+//
+// NativeCryptoError.swift
+// native_crypto_ios
+//
+// Created by Hugo Pointcheval on 25/05/2022.
+//
+
+import Foundation
+
+enum NativeCryptoError : Error {
+case decryptionError
+case encryptionError
+case messageDigestError
+case pbkdf2Error
+case cipherError
+case resultError
+case exceptionError
+}
diff --git a/packages/native_crypto_ios/ios/Classes/utils/Task.swift b/packages/native_crypto_ios/ios/Classes/utils/Task.swift
new file mode 100644
index 0000000..4d11070
--- /dev/null
+++ b/packages/native_crypto_ios/ios/Classes/utils/Task.swift
@@ -0,0 +1,52 @@
+//
+// Task.swift
+// native_crypto_ios
+//
+// Created by Hugo Pointcheval on 25/05/2022.
+//
+
+import Foundation
+
+class Task {
+
+ var task: () throws -> T
+ private var successful: Bool = false
+ private var result: T? = nil
+ private var exception: Error? = nil
+
+ init(task: @escaping () throws -> T) {
+ self.task = task
+ }
+
+ func isSuccessful() -> Bool {
+ return successful
+ }
+
+ func getResult() -> T? {
+ return result
+ }
+
+ func getException() -> Error {
+ if (exception != nil) {
+ return exception!
+ } else {
+ return NativeCryptoError.exceptionError
+ }
+ }
+
+ func call() {
+ do {
+ result = try task()
+ exception = nil
+ successful = true
+ } catch {
+ exception = error
+ result = nil
+ successful = false
+ }
+ }
+
+ func finalize(callback: (_ task: Task) -> Void) {
+ callback(self)
+ }
+}
diff --git a/native_crypto_ios/ios/native_crypto_ios.podspec b/packages/native_crypto_ios/ios/native_crypto_ios.podspec
similarity index 100%
rename from native_crypto_ios/ios/native_crypto_ios.podspec
rename to packages/native_crypto_ios/ios/native_crypto_ios.podspec
diff --git a/native_crypto_ios/pubspec.yaml b/packages/native_crypto_ios/pubspec.yaml
similarity index 95%
rename from native_crypto_ios/pubspec.yaml
rename to packages/native_crypto_ios/pubspec.yaml
index 211e4de..f4de824 100644
--- a/native_crypto_ios/pubspec.yaml
+++ b/packages/native_crypto_ios/pubspec.yaml
@@ -1,6 +1,6 @@
name: native_crypto_ios
description: iOS implementation of NativeCrypto
-version: 0.0.7
+version: 0.1.1
environment:
sdk: ">=2.15.0 <3.0.0"
diff --git a/native_crypto_platform_interface/.gitignore b/packages/native_crypto_platform_interface/.gitignore
similarity index 100%
rename from native_crypto_platform_interface/.gitignore
rename to packages/native_crypto_platform_interface/.gitignore
diff --git a/native_crypto_platform_interface/.metadata b/packages/native_crypto_platform_interface/.metadata
similarity index 100%
rename from native_crypto_platform_interface/.metadata
rename to packages/native_crypto_platform_interface/.metadata
diff --git a/packages/native_crypto_platform_interface/CHANGELOG.md b/packages/native_crypto_platform_interface/CHANGELOG.md
new file mode 100644
index 0000000..8b44888
--- /dev/null
+++ b/packages/native_crypto_platform_interface/CHANGELOG.md
@@ -0,0 +1,40 @@
+## 0.1.1
+
+ - **PERF**: x10 perfomance improvement on android with better list management.
+ - **FEAT**: export new exceptions.
+
+## 0.1.0
+
+> Breaking changes !
+
+* Follow **Federated Plugin** Flutter standard.
+
+## 0.0.6
+
+* Add KeyPair generation.
+* Rework exposed API.
+
+## 0.0.5
+
+* New API.
+* Add digest support.
+* Clean platform specific code base.
+
+## 0.0.4
+
+* Improve AES.
+
+## 0.0.3
+
+* Add PBKDF2 support.
+* Add exceptions.
+* Improve documentation.
+
+## 0.0.2
+
+* Add different key size support.
+* Improve performances.
+
+## 0.0.1
+
+* First AES cross-platform encryption & decryption implementation.
diff --git a/packages/native_crypto_platform_interface/LICENSE b/packages/native_crypto_platform_interface/LICENSE
new file mode 100644
index 0000000..68bb0c6
--- /dev/null
+++ b/packages/native_crypto_platform_interface/LICENSE
@@ -0,0 +1,23 @@
+NativeCrypto - Platform Interface
+
+MIT License
+
+Copyright (c) 2019 - 2022 Hugo Pointcheval
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.
\ No newline at end of file
diff --git a/packages/native_crypto_platform_interface/README.md b/packages/native_crypto_platform_interface/README.md
new file mode 100644
index 0000000..d1cde17
--- /dev/null
+++ b/packages/native_crypto_platform_interface/README.md
@@ -0,0 +1,12 @@
+# NativeCrypto - Platform Interface
+
+A common platform interface for the [`native_crypto`][1] plugin.
+
+This interface allows platform-specific implementations of the `native_crypto` plugin, as well as the plugin itself, to ensure they are supporting the same interface.
+
+## Usage
+
+To implement a new platform-specific implementation of `native_crypto`, extend [`NativeCryptoPlatform`][2] with an implementation that performs the platform-specific behavior, and when you register your plugin, set the default `NativeCryptoPlatform` by calling `NativeCryptoPlatform.instance = MyNativeCryptoPlatform()`.
+
+[1]: ../native_crypto
+[2]: lib/native_crypto_platform_interface.dart
\ No newline at end of file
diff --git a/packages/native_crypto_platform_interface/analysis_options.yaml b/packages/native_crypto_platform_interface/analysis_options.yaml
new file mode 100644
index 0000000..db48808
--- /dev/null
+++ b/packages/native_crypto_platform_interface/analysis_options.yaml
@@ -0,0 +1 @@
+include: package:wyatt_analysis/analysis_options.flutter.experimental.yaml
\ No newline at end of file
diff --git a/packages/native_crypto_platform_interface/lib/native_crypto_platform_interface.dart b/packages/native_crypto_platform_interface/lib/native_crypto_platform_interface.dart
new file mode 100644
index 0000000..c85bda1
--- /dev/null
+++ b/packages/native_crypto_platform_interface/lib/native_crypto_platform_interface.dart
@@ -0,0 +1,14 @@
+// Author: Hugo Pointcheval
+// Email: git@pcl.ovh
+// -----
+// File: native_crypto_platform_interface.dart
+// Created Date: 24/05/2022 19:39:11
+// Last Modified: 24/05/2022 19:39:58
+// -----
+// Copyright (c) 2022
+
+library native_crypto_platform_interface;
+
+export 'src/method_channel/method_channel_native_crypto.dart';
+export 'src/platform_interface/native_crypto_platform.dart';
+export 'src/utils/exception.dart';
diff --git a/packages/native_crypto_platform_interface/lib/src/method_channel/method_channel_native_crypto.dart b/packages/native_crypto_platform_interface/lib/src/method_channel/method_channel_native_crypto.dart
new file mode 100644
index 0000000..0559ed4
--- /dev/null
+++ b/packages/native_crypto_platform_interface/lib/src/method_channel/method_channel_native_crypto.dart
@@ -0,0 +1,154 @@
+// Author: Hugo Pointcheval
+// Email: git@pcl.ovh
+// -----
+// File: native_crypto_method_channel.dart
+// Created Date: 25/12/2021 16:58:04
+// Last Modified: 25/05/2022 10:40:29
+// -----
+// Copyright (c) 2021
+
+import 'dart:typed_data';
+
+import 'package:flutter/foundation.dart';
+import 'package:flutter/services.dart';
+import 'package:native_crypto_platform_interface/native_crypto_platform_interface.dart';
+
+/// An implementation of [NativeCryptoPlatform] that uses method channels.
+class MethodChannelNativeCrypto extends NativeCryptoPlatform {
+ /// The method channel used to interact with the native platform.
+ @visibleForTesting
+ MethodChannel channel = const MethodChannel('plugins.hugop.cl/native_crypto');
+
+ @override
+ Future digest(Uint8List data, String algorithm) async {
+ try {
+ return await channel.invokeMethod(
+ 'digest',
+ {
+ 'data': data,
+ 'algorithm': algorithm,
+ },
+ );
+ } catch (e, s) {
+ NativeCryptoException.convertPlatformException(e, s);
+ }
+ }
+
+ @override
+ Future generateSecretKey(int bitsCount) async {
+ try {
+ return await channel.invokeMethod(
+ 'generateSecretKey',
+ {
+ 'bitsCount': bitsCount,
+ },
+ );
+ } catch (e, s) {
+ NativeCryptoException.convertPlatformException(e, s);
+ }
+ }
+
+ @override
+ Future pbkdf2(
+ String password,
+ String salt,
+ int keyBytesCount,
+ int iterations,
+ String algorithm,
+ ) async {
+ try {
+ return await channel.invokeMethod(
+ 'pbkdf2',
+ {
+ 'password': password,
+ 'salt': salt,
+ 'keyBytesCount': keyBytesCount,
+ 'iterations': iterations,
+ 'algorithm': algorithm,
+ },
+ );
+ } catch (e, s) {
+ NativeCryptoException.convertPlatformException(e, s);
+ }
+ }
+
+ @override
+ Future?> encryptAsList(
+ Uint8List data,
+ Uint8List key,
+ String algorithm,
+ ) async {
+ try {
+ return await channel.invokeListMethod(
+ 'encryptAsList',
+ {
+ 'data': data,
+ 'key': key,
+ 'algorithm': algorithm,
+ },
+ );
+ } catch (e, s) {
+ NativeCryptoException.convertPlatformException(e, s);
+ }
+ }
+
+ @override
+ Future decryptAsList(
+ List data,
+ Uint8List key,
+ String algorithm,
+ ) async {
+ try {
+ return await channel.invokeMethod(
+ 'decryptAsList',
+ {
+ 'data': data,
+ 'key': key,
+ 'algorithm': algorithm,
+ },
+ );
+ } catch (e, s) {
+ NativeCryptoException.convertPlatformException(e, s);
+ }
+ }
+
+ @override
+ Future encrypt(
+ Uint8List data,
+ Uint8List key,
+ String algorithm,
+ ) async {
+ try {
+ return await channel.invokeMethod(
+ 'encrypt',
+ {
+ 'data': data,
+ 'key': key,
+ 'algorithm': algorithm,
+ },
+ );
+ } catch (e, s) {
+ NativeCryptoException.convertPlatformException(e, s);
+ }
+ }
+
+ @override
+ Future decrypt(
+ Uint8List data,
+ Uint8List key,
+ String algorithm,
+ ) async {
+ try {
+ return await channel.invokeMethod(
+ 'decrypt',
+ {
+ 'data': data,
+ 'key': key,
+ 'algorithm': algorithm,
+ },
+ );
+ } catch (e, s) {
+ NativeCryptoException.convertPlatformException(e, s);
+ }
+ }
+}
diff --git a/native_crypto_platform_interface/lib/native_crypto_platform_interface.dart b/packages/native_crypto_platform_interface/lib/src/platform_interface/native_crypto_platform.dart
similarity index 51%
rename from native_crypto_platform_interface/lib/native_crypto_platform_interface.dart
rename to packages/native_crypto_platform_interface/lib/src/platform_interface/native_crypto_platform.dart
index 1d6fbd5..b09c0d3 100644
--- a/native_crypto_platform_interface/lib/native_crypto_platform_interface.dart
+++ b/packages/native_crypto_platform_interface/lib/src/platform_interface/native_crypto_platform.dart
@@ -3,22 +3,23 @@
// -----
// File: native_crypto_platform_interface.dart
// Created Date: 25/12/2021 16:43:49
-// Last Modified: 25/12/2021 17:39:39
+// Last Modified: 25/05/2022 22:11:02
// -----
// Copyright (c) 2021
import 'dart:typed_data';
-import './src/method_channel_native_crypto.dart';
-import './src/platform_interface.dart';
+import 'package:native_crypto_platform_interface/src/method_channel/method_channel_native_crypto.dart';
+import 'package:plugin_platform_interface/plugin_platform_interface.dart';
/// The interface that implementations of path_provider must implement.
///
-/// Platform implementations should extend this class rather than implement it as `NativeCrypto`
-/// does not consider newly added methods to be breaking changes. Extending this class
-/// (using `extends`) ensures that the subclass will get the default implementation, while
-/// platform implementations that `implements` this interface will be broken by newly added
-/// [NativeCryptoPlatform] methods.
+/// Platform implementations should extend this class rather than implement
+/// it as `NativeCrypto` does not consider newly added methods to be
+/// breaking changes. Extending this class (using `extends`) ensures
+/// that the subclass will get the default implementation, while platform
+/// implementations that `implements` this interface will be
+/// broken by newly added [NativeCryptoPlatform] methods.
abstract class NativeCryptoPlatform extends PlatformInterface {
/// Constructs a NativeCryptoPlatform.
NativeCryptoPlatform() : super(token: _token);
@@ -29,13 +30,13 @@ abstract class NativeCryptoPlatform extends PlatformInterface {
/// The default instance of [NativeCryptoPlatform] to use.
///
- /// Defaults to [MethodChannelPathProvider].
+ /// Defaults to [MethodChannelNativeCrypto].
static NativeCryptoPlatform get instance => _instance;
/// Platform-specific plugins should set this with their own platform-specific
/// class that extends [NativeCryptoPlatform] when they register themselves.
static set instance(NativeCryptoPlatform instance) {
- PlatformInterface.verifyToken(instance, _token);
+ PlatformInterface.verify(instance, _token);
_instance = instance;
}
@@ -47,29 +48,45 @@ abstract class NativeCryptoPlatform extends PlatformInterface {
throw UnimplementedError('generateSecretKey is not implemented');
}
- Future generateKeyPair() {
- throw UnimplementedError('generateKeyPair is not implemented');
+ Future pbkdf2(
+ String password,
+ String salt,
+ int keyBytesCount,
+ int iterations,
+ String algorithm,
+ ) {
+ throw UnimplementedError('pbkdf2 is not implemented');
}
- Future pbkdf2(String password, String salt, int keyBytesCount,
- int iterations, String algorithm) {
- throw UnimplementedError('pbkdf2 is not implemented');
+ Future?> encryptAsList(
+ Uint8List data,
+ Uint8List key,
+ String algorithm,
+ ) {
+ throw UnimplementedError('encryptAsList is not implemented');
}
- Future encrypt(Uint8List data, Uint8List key, String algorithm) {
- throw UnimplementedError('encrypt is not implemented');
+ Future decryptAsList(
+ List data,
+ Uint8List key,
+ String algorithm,
+ ) {
+ throw UnimplementedError('decryptAsList is not implemented');
}
- Future decrypt(Uint8List data, Uint8List key, String algorithm) {
- throw UnimplementedError('decrypt is not implemented');
+ Future encrypt(
+ Uint8List data,
+ Uint8List key,
+ String algorithm,
+ ) {
+ throw UnimplementedError('encrypt is not implemented');
}
- Future generateSharedSecretKey(
- Uint8List salt,
- int keyBytesCount,
- Uint8List ephemeralPrivateKey,
- Uint8List otherPublicKey,
- String hkdfAlgorithm) {
- throw UnimplementedError('generateSharedSecretKey is not implemented');
+ Future decrypt(
+ Uint8List data,
+ Uint8List key,
+ String algorithm,
+ ) {
+ throw UnimplementedError('decrypt is not implemented');
}
}
diff --git a/packages/native_crypto_platform_interface/lib/src/utils/exception.dart b/packages/native_crypto_platform_interface/lib/src/utils/exception.dart
new file mode 100644
index 0000000..b46bb4a
--- /dev/null
+++ b/packages/native_crypto_platform_interface/lib/src/utils/exception.dart
@@ -0,0 +1,126 @@
+// Author: Hugo Pointcheval
+// Email: git@pcl.ovh
+// -----
+// File: exception.dart
+// Created Date: 24/05/2022 18:54:48
+// Last Modified: 26/05/2022 20:36:04
+// -----
+// Copyright (c) 2022
+
+// ignore_for_file: constant_identifier_names
+
+import 'dart:developer';
+
+import 'package:flutter/services.dart';
+
+enum NativeCryptoExceptionCode {
+ unknown,
+ not_implemented,
+ invalid_argument,
+ invalid_key,
+ invalid_key_length,
+ invalid_algorithm,
+ invalid_padding,
+ invalid_mode,
+ invalid_cipher,
+ invalid_data,
+ platform_not_supported,
+ platform_throws,
+ platform_returned_invalid_data,
+ platform_returned_empty_data,
+ platform_returned_null;
+
+ String get code => toString().split('.').last.toLowerCase();
+}
+
+class NativeCryptoException implements Exception {
+ NativeCryptoException({
+ this.message,
+ String? code,
+ this.stackTrace,
+ }) : code = code ?? NativeCryptoExceptionCode.unknown.code;
+
+ /// The long form message of the exception.
+ final String? message;
+
+ /// The optional code to accommodate the message.
+ final String code;
+
+ /// The stack trace which provides information to the user about the call
+ /// sequence that triggered an exception
+ final StackTrace? stackTrace;
+
+ @override
+ String toString() {
+ String output = '[NativeCryptoException/$code] $message';
+
+ if (stackTrace != null) {
+ output += '\n\n${stackTrace.toString()}';
+ }
+
+ return output;
+ }
+
+ /// Catches a [PlatformException] and returns an [Exception].
+ ///
+ /// If the [Exception] is a [PlatformException],
+ /// a [NativeCryptoException] is returned.
+ static Never convertPlatformException(
+ Object exception,
+ StackTrace stackTrace,
+ ) {
+ log(exception.toString());
+ if (exception is! Exception || exception is! PlatformException) {
+ Error.throwWithStackTrace(exception, stackTrace);
+ }
+
+ Error.throwWithStackTrace(
+ NativeCryptoException.fromPlatformException(exception, stackTrace),
+ stackTrace,
+ );
+ }
+
+ /// Converts a [PlatformException] into a [NativeCryptoException].
+ ///
+ /// A [PlatformException] can only be converted to a [NativeCryptoException]
+ /// if the `details` of the exception exist.
+ factory NativeCryptoException.fromPlatformException(
+ PlatformException platformException,
+ StackTrace stackTrace,
+ ) {
+ final Map? details = platformException.details != null
+ ? Map.from(
+ platformException.details as Map,
+ )
+ : null;
+
+ String code = NativeCryptoExceptionCode.unknown.code;
+ String message = platformException.message ?? '';
+
+ if (details != null) {
+ code = details['code'] ?? code;
+ message = details['message'] ?? message;
+ }
+
+ return NativeCryptoException(
+ message: message,
+ code: code,
+ stackTrace: stackTrace,
+ );
+ }
+
+ @override
+ // ignore: avoid_equals_and_hash_code_on_mutable_classes
+ bool operator ==(Object other) {
+ if (identical(this, other)) return true;
+
+ return other is NativeCryptoException &&
+ other.message == message &&
+ other.code == code &&
+ other.stackTrace == stackTrace;
+ }
+
+ @override
+ // ignore: avoid_equals_and_hash_code_on_mutable_classes
+ int get hashCode => message.hashCode ^ code.hashCode ^ stackTrace.hashCode;
+}
diff --git a/packages/native_crypto_platform_interface/pubspec.yaml b/packages/native_crypto_platform_interface/pubspec.yaml
new file mode 100644
index 0000000..57593de
--- /dev/null
+++ b/packages/native_crypto_platform_interface/pubspec.yaml
@@ -0,0 +1,25 @@
+name: native_crypto_platform_interface
+description: A common interface for NativeCrypto plugin.
+version: 0.1.1
+
+environment:
+ sdk: ">=2.17.0 <3.0.0"
+ flutter: ">=2.5.0"
+
+dependencies:
+ flutter:
+ sdk: flutter
+
+ plugin_platform_interface: ^2.1.2
+
+dev_dependencies:
+ flutter_test:
+ sdk: flutter
+
+ mockito: ^5.2.0
+
+ wyatt_analysis:
+ git:
+ url: https://git.wyatt-studio.fr/Wyatt-FOSS/wyatt-packages
+ ref: wyatt_analysis-v2.1.0
+ path: packages/wyatt_analysis
diff --git a/packages/native_crypto_platform_interface/test/method_channel/method_channel_native_crypto_test.dart b/packages/native_crypto_platform_interface/test/method_channel/method_channel_native_crypto_test.dart
new file mode 100644
index 0000000..28c01a1
--- /dev/null
+++ b/packages/native_crypto_platform_interface/test/method_channel/method_channel_native_crypto_test.dart
@@ -0,0 +1,175 @@
+// Author: Hugo Pointcheval
+// Email: git@pcl.ovh
+// -----
+// File: method_channel_native_crypto_test.dart
+// Created Date: 25/05/2022 22:47:41
+// Last Modified: 25/05/2022 23:22:44
+// -----
+// Copyright (c) 2022
+
+import 'dart:typed_data';
+
+import 'package:flutter/services.dart';
+import 'package:flutter_test/flutter_test.dart';
+import 'package:native_crypto_platform_interface/src/method_channel/method_channel_native_crypto.dart';
+
+void main() {
+ TestWidgetsFlutterBinding
+ .ensureInitialized(); // Required for setMockMethodCallHandler
+
+ group('$MethodChannelNativeCrypto', () {
+ const MethodChannel channel =
+ MethodChannel('plugins.hugop.cl/native_crypto');
+ final List log = [];
+ final MethodChannelNativeCrypto nativeCrypto = MethodChannelNativeCrypto();
+
+ TestDefaultBinaryMessengerBinding.instance?.defaultBinaryMessenger
+ .setMockMethodCallHandler(channel, (MethodCall call) async {
+ log.add(call);
+ return null;
+ });
+
+ // Run after each test.
+ tearDown(log.clear);
+
+ test('digest', () async {
+ await nativeCrypto.digest(Uint8List(0), 'sha256');
+ expect(
+ log,
+ [
+ isMethodCall(
+ 'digest',
+ arguments: {
+ 'data': Uint8List(0),
+ 'algorithm': 'sha256',
+ },
+ ),
+ ],
+ );
+ });
+
+ test('generateSecretKey', () async {
+ await nativeCrypto.generateSecretKey(256);
+ expect(
+ log,
+ [
+ isMethodCall(
+ 'generateSecretKey',
+ arguments: {
+ 'bitsCount': 256,
+ },
+ ),
+ ],
+ );
+ });
+
+ test('pbkdf2', () async {
+ await nativeCrypto.pbkdf2(
+ 'password',
+ 'salt',
+ 32,
+ 10000,
+ 'sha256',
+ );
+ expect(
+ log,
+ [
+ isMethodCall(
+ 'pbkdf2',
+ arguments: {
+ 'password': 'password',
+ 'salt': 'salt',
+ 'keyBytesCount': 32,
+ 'iterations': 10000,
+ 'algorithm': 'sha256',
+ },
+ ),
+ ],
+ );
+ });
+
+ test('encryptAsList', () async {
+ await nativeCrypto.encryptAsList(
+ Uint8List(0),
+ Uint8List(0),
+ 'aes',
+ );
+ expect(
+ log,
+