From 35c5d8cf5adb844195d438901d2e78ca61d348ae Mon Sep 17 00:00:00 2001 From: Adel HB Date: Mon, 2 Mar 2026 17:57:10 +0100 Subject: [PATCH 1/6] Added most necessary files for publishing --- CHANGELOG.md | 41 +++++- CONTRIBUTING.md | 229 +++++++++++++++++++++++++++++++ LICENSE | 22 ++- README.md | 8 +- RELEASE_GUIDE.md | 223 ++++++++++++++++++++++++++++++ lib/src/rust/api/encryption.dart | 4 + lib/src/rust/api/kdf/hkdf.dart | 12 ++ pubspec.yaml | 60 ++------ 8 files changed, 548 insertions(+), 51 deletions(-) create mode 100644 CONTRIBUTING.md create mode 100644 RELEASE_GUIDE.md diff --git a/CHANGELOG.md b/CHANGELOG.md index 41cc7d8..cbdb612 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,42 @@ ## 0.0.1 -* TODO: Describe initial release. +Initial release of M-Security — a native Rust cryptographic SDK for Flutter. + +### Authenticated Encryption (AEAD) + +- **AES-256-GCM** — Industry-standard authenticated encryption with 32-byte keys, 12-byte auto-generated nonces, and 16-byte authentication tags. +- **ChaCha20-Poly1305** — High-performance alternative optimized for mobile processors lacking dedicated AES hardware. +- Unified `CipherHandle` interface for both ciphers (create, encrypt, decrypt, generate key). +- Output format: `nonce || ciphertext || tag`. + +### Hashing + +- **BLAKE3** — Ultra-fast integrity verification with one-shot and streaming APIs via `HasherHandle`. +- **SHA-3-256 (Keccak)** — NIST-standard hashing with one-shot and streaming APIs. +- **Argon2id** — PHC-winning password hashing with Mobile (64 MiB) and Desktop (256 MiB) presets, automatic salt generation, and PHC string output. + +### Key Derivation (KDF) + +- **HKDF-SHA256** — RFC 5869-compliant key derivation with `derive`, `extract`, and `expand` operations. Output range: 1-8160 bytes. + +### Security + +- All key material held in Rust behind opaque `#[frb(opaque)]` handles — raw keys never cross the FFI boundary. +- Secure memory management with `ZeroizeOnDrop` on all key-holding structs. +- `clippy::unwrap_used = "deny"` — no unwrap in FFI-visible code. +- `panic = "abort"` in release profile — no undefined behavior from panics crossing FFI. +- Nonces generated internally via `OsRng` — callers never handle nonces. + +### Platform Support + +- Android (ARM64, ARM32) +- iOS (ARM64, Simulator) +- macOS (ARM64, Intel) +- Linux (x86_64) +- Windows (x86_64) + +### Infrastructure + +- CI pipeline with Rust linting/testing, Dart analysis, and platform builds (Android, iOS, Linux). +- Integration tests for all cryptographic operations. +- Flutter Rust Bridge 2.11.1 for FFI code generation. diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md new file mode 100644 index 0000000..899e5c9 --- /dev/null +++ b/CONTRIBUTING.md @@ -0,0 +1,229 @@ +# Contributing to M-Security + +Thank you for your interest in contributing to M-Security! This guide will help you get started. + +## Table of Contents + +- [Code of Conduct](#code-of-conduct) +- [Getting Started](#getting-started) +- [Development Setup](#development-setup) +- [Project Structure](#project-structure) +- [Making Changes](#making-changes) +- [Coding Standards](#coding-standards) +- [Testing](#testing) +- [Submitting a Pull Request](#submitting-a-pull-request) +- [Security](#security) + +## Code of Conduct + +By participating in this project, you agree to maintain a respectful and inclusive environment. Be kind, constructive, and professional in all interactions. + +## Getting Started + +1. **Fork** the repository on GitHub. +2. **Clone** your fork locally: + ```bash + git clone git@github.com:/M-Security.git + cd M-Security + ``` +3. **Add upstream** remote: + ```bash + git remote add upstream git@github.com:MicroClub-USTHB/M-Security.git + ``` + +## Development Setup + +### Prerequisites + +- **Rust** (stable toolchain): + ```bash + curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh + ``` +- **Flutter SDK** (stable channel) with Dart SDK ^3.10.8 +- **Flutter Rust Bridge codegen**: + ```bash + cargo install flutter_rust_bridge_codegen + ``` +- **Platform-specific tools**: + - **macOS/iOS**: Xcode with command line tools + - **Android**: Android NDK (r27c recommended) + - **Linux**: `clang`, `cmake`, `ninja-build`, `pkg-config`, `libgtk-3-dev` + - **Windows**: Visual Studio Build Tools + LLVM + +### Building the Project + +```bash +# Install Flutter dependencies +flutter pub get + +# Build the Rust library +cd rust && cargo build && cd .. + +# Generate FFI bindings +flutter_rust_bridge_codegen generate + +# Generate Freezed data classes +dart run build_runner build --delete-conflicting-outputs + +# Run the example app +cd example && flutter run +``` + +## Project Structure + +``` +M-Security/ +├── lib/ # Dart public API +│ ├── m_security.dart # Main entry point (exports) +│ └── src/ +│ ├── encryption/ # AES-GCM, ChaCha20 service wrappers +│ ├── hashing/ # Argon2id wrapper +│ ├── kdf/ # HKDF wrapper +│ └── rust/ # Generated FFI bindings (do not edit) +├── rust/ # Rust crypto core +│ └── src/ +│ ├── api/ # Public API (scanned by FRB) +│ │ ├── encryption/ # AES-GCM, ChaCha20, Noop +│ │ ├── hashing/ # Argon2, BLAKE3, SHA-3 +│ │ └── kdf/ # HKDF-SHA256 +│ └── core/ # Internal utilities +│ ├── secret.rs # SecretBuffer with ZeroizeOnDrop +│ ├── traits.rs # Encryption, Hasher, Kdf traits +│ ├── error.rs # CryptoError enum +│ └── rng.rs # Random number generation +├── rust_builder/ # Rust build system integration +├── integration_test/ # Dart integration tests +├── example/ # Flutter example app +└── .github/workflows/ # CI pipeline +``` + +### Key Concepts + +- **`rust/src/api/`** — Everything in this directory is scanned by Flutter Rust Bridge and exposed to Dart. This is where new cryptographic primitives should be added. +- **`rust/src/core/`** — Internal Rust utilities. Not exposed to Dart. +- **`lib/src/rust/`** — Auto-generated by FRB. **Never edit these files manually.** +- **`lib/src/encryption/`, `lib/src/hashing/`, `lib/src/kdf/`** — Dart wrapper services providing a clean, idiomatic API on top of the generated FFI bindings. + +## Making Changes + +### Branch Naming + +Create a feature branch from `dev` (not `main`): + +```bash +git checkout dev +git pull upstream dev +git checkout -b / +``` + +Branch types: +- `feat/` — New feature or algorithm +- `fix/` — Bug fix +- `refactor/` — Code restructuring +- `docs/` — Documentation changes +- `ci/` — CI/CD pipeline changes +- `test/` — Test additions or fixes + +### Adding a New Cryptographic Primitive + +1. **Rust implementation** — Add your module under `rust/src/api//`. +2. **Implement the appropriate trait** from `rust/src/core/traits.rs` (`Encryption`, `Hasher`, or `Kdf`). +3. **Use `SecretBuffer`** for all key material (ensures `ZeroizeOnDrop`). +4. **Write Rust unit tests** in the same file using `#[cfg(test)]` module. +5. **Regenerate FFI bindings**: `flutter_rust_bridge_codegen generate`. +6. **Create a Dart wrapper** in `lib/src//` following existing patterns. +7. **Export it** from `lib/m_security.dart`. +8. **Write integration tests** in `integration_test/`. + +## Coding Standards + +### Rust + +- **No `unwrap()` in FFI-visible code** — The project enforces `clippy::unwrap_used = "deny"`. Use `Result` for all fallible operations. +- **Derive `ZeroizeOnDrop`** on all structs holding key material. +- **Run Clippy** before committing: + ```bash + cd rust && cargo clippy --all-targets -- -D warnings + ``` +- Use `thiserror` for error types. + +### Dart + +- Follow the [Flutter style guide](https://docs.flutter.dev/style-guide). +- Run the analyzer: + ```bash + dart analyze lib/ integration_test/ + ``` + +### General + +- Keep commits atomic — one logical change per commit. +- Write clear commit messages following [Conventional Commits](https://www.conventionalcommits.org/): + ``` + feat(encryption): add XChaCha20-Poly1305 cipher + fix(argon2): correct memory allocation on mobile preset + docs: update README with new algorithm table + ``` + +## Testing + +### Rust Unit Tests + +```bash +cd rust && cargo test +``` + +### Dart Integration Tests + +Integration tests require a running device or simulator: + +```bash +cd example +flutter test integration_test/aes_gcm_test.dart +flutter test integration_test/chacha20_test.dart +flutter test integration_test/hashing_test.dart +flutter test integration_test/argon2_test.dart +flutter test integration_test/hkdf_test.dart +``` + +### CI Pipeline + +All pull requests must pass the CI pipeline, which runs: + +1. Rust lint (Clippy) and tests +2. Dart codegen and static analysis +3. Platform builds (Android, iOS, Linux) + +## Submitting a Pull Request + +1. **Ensure all tests pass** locally (both Rust and Dart). +2. **Push** your branch to your fork: + ```bash + git push origin + ``` +3. **Open a PR** against the `dev` branch on the upstream repository. +4. **Fill in the PR template** with: + - A clear description of the change + - Related issue numbers (if any) + - Testing steps +5. **Wait for CI** to pass and for a maintainer review. +6. **Address review feedback** with additional commits (do not force-push during review). + +### PR Checklist + +- [ ] Code compiles without warnings (`cargo clippy`, `dart analyze`) +- [ ] All existing tests pass +- [ ] New tests added for new functionality +- [ ] Documentation updated if public API changed +- [ ] CHANGELOG.md updated under an `## Unreleased` section +- [ ] Commit messages follow Conventional Commits + +## Security + +If you discover a security vulnerability, **do not open a public issue**. Instead, please report it privately by emailing the maintainers or using [GitHub Security Advisories](https://github.com/MicroClub-USTHB/M-Security/security/advisories/new). + +Cryptographic code requires extra scrutiny: +- Never introduce `unsafe` blocks without justification and review. +- All key material must be zeroized on drop. +- Never expose raw key bytes across the FFI boundary. +- Use `OsRng` for all random number generation (never `thread_rng` or similar). diff --git a/LICENSE b/LICENSE index ba75c69..3ef57f1 100644 --- a/LICENSE +++ b/LICENSE @@ -1 +1,21 @@ -TODO: Add your license here. +MIT License + +Copyright (c) 2025 MicroClub-USTHB + +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. diff --git a/README.md b/README.md index bd6801c..fe3f3a8 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,10 @@ # M-Security -A native Rust cryptographic SDK for Flutter. High-performance hashing, authenticated encryption, and key derivation — all implemented in Rust and exposed to Dart via [Flutter Rust Bridge](https://github.com/aspect-build/aspect-cli/issues/flutter_rust_bridge) (FRB). +[![pub package](https://img.shields.io/pub/v/m_security.svg)](https://pub.dev/packages/m_security) +[![CI](https://github.com/MicroClub-USTHB/M-Security/actions/workflows/ci.yml/badge.svg)](https://github.com/MicroClub-USTHB/M-Security/actions/workflows/ci.yml) +[![License: MIT](https://img.shields.io/badge/License-MIT-blue.svg)](https://opensource.org/licenses/MIT) + +A native Rust cryptographic SDK for Flutter. High-performance hashing, authenticated encryption, and key derivation — all implemented in Rust and exposed to Dart via [Flutter Rust Bridge](https://cjycode.com/flutter_rust_bridge/) (FRB). ## Features @@ -17,7 +21,7 @@ A native Rust cryptographic SDK for Flutter. High-performance hashing, authentic | Algorithm | Key | Nonce | Tag | Output Format | |-----------|-----|-------|-----|---------------| | **AES-256-GCM** | 32 B | 12 B (auto) | 16 B | `nonce \|\| ciphertext \|\| tag` | -| **ChaCha20-Poly1305** | 32 B | 12 B (auto) | `16 B | `nonce \|\| ciphertext \|\| tag` | +| **ChaCha20-Poly1305** | 32 B | 12 B (auto) | 16 B | `nonce \|\| ciphertext \|\| tag` | Both ciphers use the same `CipherHandle` interface — create, encrypt, decrypt, generate key. diff --git a/RELEASE_GUIDE.md b/RELEASE_GUIDE.md new file mode 100644 index 0000000..3be96d9 --- /dev/null +++ b/RELEASE_GUIDE.md @@ -0,0 +1,223 @@ +# Release Guide + +This document describes how to create a new release of M-Security after merging changes to the `main` branch. + +## Versioning + +M-Security follows [Semantic Versioning](https://semver.org/) (SemVer): + +- **MAJOR** (`X.0.0`) — Breaking API changes (e.g., removing a function, changing a return type). +- **MINOR** (`0.X.0`) — New features, backward-compatible (e.g., adding a new cipher or hash algorithm). +- **PATCH** (`0.0.X`) — Bug fixes and patches, backward-compatible (e.g., fixing edge case in encryption). + +For pre-release versions, append a suffix: `0.2.0-dev.1`, `1.0.0-beta.1`. + +## Release Workflow + +### 1. Prepare the Release Branch + +All development happens on the `dev` branch. When ready to release: + +```bash +# Ensure dev is up to date +git checkout dev +git pull origin dev + +# Create a release branch +git checkout -b release/vX.Y.Z +``` + +### 2. Update Version Numbers + +Update the version in these files: + +**`pubspec.yaml`** (root): +```yaml +version: X.Y.Z +``` + +**`rust/Cargo.toml`**: +```toml +[package] +version = "X.Y.Z" +``` + +**`rust_builder/pubspec.yaml`** (if applicable): +```yaml +version: X.Y.Z +``` + +### 3. Update CHANGELOG.md + +Move the `## Unreleased` section content under a new version header with the current date: + +```markdown +## X.Y.Z - YYYY-MM-DD + +### Added +- New feature description + +### Changed +- Changed behavior description + +### Fixed +- Bug fix description +``` + +Follow [Keep a Changelog](https://keepachangelog.com/) format with these categories: +- **Added** — New features +- **Changed** — Changes to existing functionality +- **Deprecated** — Features that will be removed in future versions +- **Removed** — Removed features +- **Fixed** — Bug fixes +- **Security** — Vulnerability fixes + +### 4. Run All Checks + +```bash +# Rust checks +cd rust +cargo clippy --all-targets -- -D warnings +cargo test +cd .. + +# Dart checks +flutter pub get +flutter_rust_bridge_codegen generate +dart run build_runner build --delete-conflicting-outputs +dart analyze lib/ integration_test/ + +# Run integration tests (requires a device/simulator) +cd example +flutter test integration_test/ +cd .. +``` + +### 5. Open a Pull Request to `main` + +```bash +git add -A +git commit -m "chore(release): prepare vX.Y.Z" +git push origin release/vX.Y.Z +``` + +Open a PR from `release/vX.Y.Z` to `main`. Ensure CI passes and get a maintainer review. + +### 6. Merge and Tag + +After the PR is approved and merged: + +```bash +git checkout main +git pull origin main + +# Create an annotated tag +git tag -a vX.Y.Z -m "Release vX.Y.Z" + +# Push the tag +git push origin vX.Y.Z +``` + +### 7. Create a GitHub Release + +Using the GitHub CLI: + +```bash +gh release create vX.Y.Z \ + --title "vX.Y.Z" \ + --notes-file CHANGELOG_EXCERPT.md +``` + +Or via the GitHub web UI: + +1. Go to [Releases](https://github.com/MicroClub-USTHB/M-Security/releases). +2. Click **"Draft a new release"**. +3. Select the `vX.Y.Z` tag. +4. Set the title to `vX.Y.Z`. +5. Copy the relevant CHANGELOG.md section into the description. +6. Click **"Publish release"**. + +### 8. Publish to pub.dev + +> **First-time setup**: Ensure you are authenticated with `dart pub login` and that the package publisher is configured on pub.dev. See [Verified Publishers](https://dart.dev/tools/pub/verified-publishers). + +```bash +# Dry run first — review what will be published +dart pub publish --dry-run + +# If everything looks good, publish +dart pub publish +``` + +**Important notes:** +- Publishing is **permanent** — you cannot unpublish a version (only retract within 7 days). +- Ensure `lib/src/rust/` generated files are included (they are needed by consumers). +- The `.pubignore` or `.gitignore` controls which files are excluded from the published package. +- Verify the package size is under 100 MB (gzip) / 256 MB (uncompressed). + +### 9. Post-Release + +After publishing: + +```bash +# Merge main back into dev to sync version numbers +git checkout dev +git pull origin dev +git merge main +git push origin dev +``` + +Add a new `## Unreleased` section at the top of `CHANGELOG.md` on `dev`: + +```markdown +## Unreleased + +### Added + +### Changed + +### Fixed +``` + +## Quick Reference + +| Step | Command | +|------|---------| +| Create release branch | `git checkout -b release/vX.Y.Z` | +| Run Rust tests | `cd rust && cargo test` | +| Run Dart analysis | `dart analyze lib/ integration_test/` | +| Dry-run publish | `dart pub publish --dry-run` | +| Tag the release | `git tag -a vX.Y.Z -m "Release vX.Y.Z"` | +| Push the tag | `git push origin vX.Y.Z` | +| Create GitHub release | `gh release create vX.Y.Z --title "vX.Y.Z"` | +| Publish to pub.dev | `dart pub publish` | + +## Hotfix Releases + +For urgent fixes to the current stable release: + +```bash +# Branch from the release tag +git checkout -b hotfix/vX.Y.Z main + +# Make the fix, then follow steps 2-9 above with an incremented PATCH version +``` + +## Checklist + +Use this checklist when preparing a release: + +- [ ] Version updated in `pubspec.yaml` +- [ ] Version updated in `rust/Cargo.toml` +- [ ] CHANGELOG.md updated with release date +- [ ] All Rust tests pass (`cargo test`) +- [ ] Clippy clean (`cargo clippy -- -D warnings`) +- [ ] Dart analysis clean (`dart analyze`) +- [ ] Integration tests pass +- [ ] CI pipeline passes on the PR +- [ ] PR merged to `main` +- [ ] Git tag created and pushed +- [ ] GitHub Release created +- [ ] Published to pub.dev (`dart pub publish`) +- [ ] `main` merged back into `dev` +- [ ] `Unreleased` section added to CHANGELOG.md on `dev` diff --git a/lib/src/rust/api/encryption.dart b/lib/src/rust/api/encryption.dart index ac451e1..5e2d049 100644 --- a/lib/src/rust/api/encryption.dart +++ b/lib/src/rust/api/encryption.dart @@ -10,6 +10,10 @@ import 'package:flutter_rust_bridge/flutter_rust_bridge_for_generated.dart'; // These functions are ignored because they are not marked as `pub`: `new` /// Create a noop encryption handle (for testing FRB opaque pattern). +/// +/// # Panics +/// Panics at runtime unless the `testing` feature is enabled. +/// **Never** enable the `testing` feature in production builds. Future createNoopEncryption() => RustLib.instance.api.crateApiEncryptionCreateNoopEncryption(); diff --git a/lib/src/rust/api/kdf/hkdf.dart b/lib/src/rust/api/kdf/hkdf.dart index d285253..21a3e13 100644 --- a/lib/src/rust/api/kdf/hkdf.dart +++ b/lib/src/rust/api/kdf/hkdf.dart @@ -9,6 +9,10 @@ import 'package:flutter_rust_bridge/flutter_rust_bridge_for_generated.dart'; /// One-shot HKDF-SHA256: extract + expand in a single call. /// Returns `output_len` bytes of derived key material. +/// +/// # Security +/// Input key material (`ikm`, `salt`) is zeroed before the function returns. +/// The caller is responsible for zeroizing the returned `Vec`. Uint8List hkdfDerive({ required List ikm, Uint8List? salt, @@ -22,10 +26,18 @@ Uint8List hkdfDerive({ ); /// HKDF-Extract: produce a pseudorandom key (PRK) from input key material. +/// +/// # Security +/// Input key material (`ikm`, `salt`) is zeroed before the function returns. +/// The caller is responsible for zeroizing the returned PRK. Uint8List hkdfExtract({required List ikm, Uint8List? salt}) => RustLib.instance.api.crateApiKdfHkdfHkdfExtract(ikm: ikm, salt: salt); /// HKDF-Expand: expand a PRK into `output_len` bytes of derived key material. +/// +/// # Security +/// The input PRK is zeroed before the function returns. +/// The caller is responsible for zeroizing the returned key material. Future hkdfExpand({ required List prk, required List info, diff --git a/pubspec.yaml b/pubspec.yaml index 5fd5e09..4d31668 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -1,7 +1,18 @@ name: m_security -description: "A new Flutter plugin project." +description: >- + A high-performance cryptographic SDK for Flutter powered by native Rust via FFI. + Provides authenticated encryption (AES-256-GCM, ChaCha20-Poly1305), modern hashing + (BLAKE3, SHA-3, Argon2id), and key derivation (HKDF-SHA256) with secure memory management. version: 0.0.1 -homepage: +homepage: https://github.com/MicroClub-USTHB/M-Security +repository: https://github.com/MicroClub-USTHB/M-Security +issue_tracker: https://github.com/MicroClub-USTHB/M-Security/issues +topics: + - cryptography + - encryption + - security + - rust + - ffi environment: sdk: ^3.10.8 @@ -26,21 +37,7 @@ dev_dependencies: build_runner: ^2.11.1 test: ^1.29.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 packages. flutter: - # This section identifies this Flutter project as a plugin project. - # The 'pluginClass' specifies the class (in Java, Kotlin, Swift, Objective-C, etc.) - # which should be registered in the plugin registry. This is required for - # using method channels. - # The Android 'package' specifies package in which the registered class is. - # This is required for using method channels on Android. - # The 'ffiPlugin' specifies that native code should be built and bundled. - # This is required for using `dart:ffi`. - # All these are used by the tooling to maintain consistency when - # adding or updating assets for this project. plugin: platforms: android: @@ -54,34 +51,3 @@ flutter: pluginClass: MSecurityPlugin windows: pluginClass: MSecurityPluginCApi - - # To add assets to your plugin package, add an assets section, like this: - # assets: - # - images/a_dot_burr.jpeg - # - images/a_dot_ham.jpeg - # - # For details regarding assets in packages, see - # https://flutter.dev/to/asset-from-package - # - # An image asset can refer to one or more resolution-specific "variants", see - # https://flutter.dev/to/resolution-aware-images - - # To add custom fonts to your plugin package, 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 in packages, see - # https://flutter.dev/to/font-from-package From 3a785419c0530dade14ca816ff3b36845df81439 Mon Sep 17 00:00:00 2001 From: Adel HB Date: Mon, 2 Mar 2026 18:38:53 +0100 Subject: [PATCH 2/6] Cleaned some files to make it ready for publishing --- .gitignore | 2 +- .pubignore | 26 + CONTRIBUTING.md | 2 +- RELEASE_GUIDE.md | 5 - android/build.gradle | 66 +- android/src/main/AndroidManifest.xml | 2 +- .../com/example/m_security/MSecurityPlugin.kt | 38 - .../example/m_security/MSecurityPluginTest.kt | 27 - .../cargokit => cargokit}/.gitignore | 0 {rust_builder/cargokit => cargokit}/LICENSE | 0 {rust_builder/cargokit => cargokit}/README | 0 .../cargokit => cargokit}/build_pod.sh | 0 .../build_tool/README.md | 0 .../build_tool/analysis_options.yaml | 0 .../build_tool/bin/build_tool.dart | 0 .../build_tool/lib/build_tool.dart | 0 .../lib/src/android_environment.dart | 0 .../lib/src/artifacts_provider.dart | 0 .../build_tool/lib/src/build_cmake.dart | 0 .../build_tool/lib/src/build_gradle.dart | 0 .../build_tool/lib/src/build_pod.dart | 0 .../build_tool/lib/src/build_tool.dart | 0 .../build_tool/lib/src/builder.dart | 0 .../build_tool/lib/src/cargo.dart | 0 .../build_tool/lib/src/crate_hash.dart | 0 .../build_tool/lib/src/environment.dart | 0 .../build_tool/lib/src/logging.dart | 0 .../build_tool/lib/src/options.dart | 0 .../lib/src/precompile_binaries.dart | 0 .../build_tool/lib/src/rustup.dart | 0 .../build_tool/lib/src/target.dart | 0 .../build_tool/lib/src/util.dart | 0 .../build_tool/lib/src/verify_binaries.dart | 0 .../build_tool/pubspec.lock | 0 .../build_tool/pubspec.yaml | 0 .../cmake/cargokit.cmake | 0 .../cmake/resolve_symlinks.ps1 | 0 .../gradle/plugin.gradle | 0 .../cargokit => cargokit}/run_build_tool.cmd | 0 .../cargokit => cargokit}/run_build_tool.sh | 0 example/ios/RunnerTests/RunnerTests.swift | 24 +- .../flutter/generated_plugin_registrant.cc | 4 - example/linux/flutter/generated_plugins.cmake | 3 +- .../Flutter/GeneratedPluginRegistrant.swift | 2 - example/macos/RunnerTests/RunnerTests.swift | 25 +- example/pubspec.lock | 7 - .../flutter/generated_plugin_registrant.cc | 3 - .../windows/flutter/generated_plugins.cmake | 3 +- ios/Classes/MSecurityPlugin.swift | 19 - .../ios => ios}/Classes/dummy_file.c | 0 ios/m_security.podspec | 38 +- lib/src/rust/api/hashing.dart | 54 ++ lib/src/rust/api/hashing/argon2.dart | 57 ++ lib/src/rust/core/error.dart | 31 + lib/src/rust/core/error.freezed.dart | 710 ++++++++++++++++++ linux/CMakeLists.txt | 81 +- linux/include/m_security/m_security_plugin.h | 26 - linux/m_security_plugin.cc | 76 -- linux/m_security_plugin_private.h | 10 - linux/test/m_security_plugin_test.cc | 31 - macos/Classes/MSecurityPlugin.swift | 19 - .../macos => macos}/Classes/dummy_file.c | 0 macos/m_security.podspec | 40 +- pubspec.yaml | 15 +- rust_builder/.gitignore | 29 - rust_builder/README.md | 1 - rust_builder/android/.gitignore | 9 - rust_builder/android/build.gradle | 56 -- rust_builder/android/settings.gradle | 1 - .../android/src/main/AndroidManifest.xml | 3 - rust_builder/ios/rust_lib_m_security.podspec | 45 -- rust_builder/linux/CMakeLists.txt | 19 - .../macos/rust_lib_m_security.podspec | 44 -- rust_builder/pubspec.yaml | 34 - rust_builder/windows/.gitignore | 17 - rust_builder/windows/CMakeLists.txt | 20 - windows/CMakeLists.txt | 86 +-- .../m_security/m_security_plugin_c_api.h | 23 - windows/m_security_plugin.cpp | 59 -- windows/m_security_plugin.h | 31 - windows/m_security_plugin_c_api.cpp | 12 - windows/test/m_security_plugin_test.cpp | 43 -- 82 files changed, 987 insertions(+), 991 deletions(-) create mode 100644 .pubignore delete mode 100644 android/src/main/kotlin/com/example/m_security/MSecurityPlugin.kt delete mode 100644 android/src/test/kotlin/com/example/m_security/MSecurityPluginTest.kt rename {rust_builder/cargokit => cargokit}/.gitignore (100%) rename {rust_builder/cargokit => cargokit}/LICENSE (100%) rename {rust_builder/cargokit => cargokit}/README (100%) rename {rust_builder/cargokit => cargokit}/build_pod.sh (100%) mode change 100644 => 100755 rename {rust_builder/cargokit => cargokit}/build_tool/README.md (100%) rename {rust_builder/cargokit => cargokit}/build_tool/analysis_options.yaml (100%) rename {rust_builder/cargokit => cargokit}/build_tool/bin/build_tool.dart (100%) rename {rust_builder/cargokit => cargokit}/build_tool/lib/build_tool.dart (100%) rename {rust_builder/cargokit => cargokit}/build_tool/lib/src/android_environment.dart (100%) rename {rust_builder/cargokit => cargokit}/build_tool/lib/src/artifacts_provider.dart (100%) rename {rust_builder/cargokit => cargokit}/build_tool/lib/src/build_cmake.dart (100%) rename {rust_builder/cargokit => cargokit}/build_tool/lib/src/build_gradle.dart (100%) rename {rust_builder/cargokit => cargokit}/build_tool/lib/src/build_pod.dart (100%) rename {rust_builder/cargokit => cargokit}/build_tool/lib/src/build_tool.dart (100%) rename {rust_builder/cargokit => cargokit}/build_tool/lib/src/builder.dart (100%) rename {rust_builder/cargokit => cargokit}/build_tool/lib/src/cargo.dart (100%) rename {rust_builder/cargokit => cargokit}/build_tool/lib/src/crate_hash.dart (100%) rename {rust_builder/cargokit => cargokit}/build_tool/lib/src/environment.dart (100%) rename {rust_builder/cargokit => cargokit}/build_tool/lib/src/logging.dart (100%) rename {rust_builder/cargokit => cargokit}/build_tool/lib/src/options.dart (100%) rename {rust_builder/cargokit => cargokit}/build_tool/lib/src/precompile_binaries.dart (100%) rename {rust_builder/cargokit => cargokit}/build_tool/lib/src/rustup.dart (100%) rename {rust_builder/cargokit => cargokit}/build_tool/lib/src/target.dart (100%) rename {rust_builder/cargokit => cargokit}/build_tool/lib/src/util.dart (100%) rename {rust_builder/cargokit => cargokit}/build_tool/lib/src/verify_binaries.dart (100%) rename {rust_builder/cargokit => cargokit}/build_tool/pubspec.lock (100%) rename {rust_builder/cargokit => cargokit}/build_tool/pubspec.yaml (100%) rename {rust_builder/cargokit => cargokit}/cmake/cargokit.cmake (100%) rename {rust_builder/cargokit => cargokit}/cmake/resolve_symlinks.ps1 (100%) rename {rust_builder/cargokit => cargokit}/gradle/plugin.gradle (100%) rename {rust_builder/cargokit => cargokit}/run_build_tool.cmd (100%) rename {rust_builder/cargokit => cargokit}/run_build_tool.sh (100%) delete mode 100644 ios/Classes/MSecurityPlugin.swift rename {rust_builder/ios => ios}/Classes/dummy_file.c (100%) create mode 100644 lib/src/rust/api/hashing.dart create mode 100644 lib/src/rust/api/hashing/argon2.dart create mode 100644 lib/src/rust/core/error.dart create mode 100644 lib/src/rust/core/error.freezed.dart delete mode 100644 linux/include/m_security/m_security_plugin.h delete mode 100644 linux/m_security_plugin.cc delete mode 100644 linux/m_security_plugin_private.h delete mode 100644 linux/test/m_security_plugin_test.cc delete mode 100644 macos/Classes/MSecurityPlugin.swift rename {rust_builder/macos => macos}/Classes/dummy_file.c (100%) delete mode 100644 rust_builder/.gitignore delete mode 100644 rust_builder/README.md delete mode 100644 rust_builder/android/.gitignore delete mode 100644 rust_builder/android/build.gradle delete mode 100644 rust_builder/android/settings.gradle delete mode 100644 rust_builder/android/src/main/AndroidManifest.xml delete mode 100644 rust_builder/ios/rust_lib_m_security.podspec delete mode 100644 rust_builder/linux/CMakeLists.txt delete mode 100644 rust_builder/macos/rust_lib_m_security.podspec delete mode 100644 rust_builder/pubspec.yaml delete mode 100644 rust_builder/windows/.gitignore delete mode 100644 rust_builder/windows/CMakeLists.txt delete mode 100644 windows/include/m_security/m_security_plugin_c_api.h delete mode 100644 windows/m_security_plugin.cpp delete mode 100644 windows/m_security_plugin.h delete mode 100644 windows/m_security_plugin_c_api.cpp delete mode 100644 windows/test/m_security_plugin_test.cpp diff --git a/.gitignore b/.gitignore index 0575e19..862b46f 100644 --- a/.gitignore +++ b/.gitignore @@ -18,7 +18,7 @@ migrate_working_dir/ .vscode/ # Generated by flutter-rust-bridge — regenerate with `flutter_rust_bridge_codegen generate` -lib/src/rust +# NOTE: lib/src/rust/ is NOT ignored — it must be committed for pub.dev publishing rust/android/ rust/example/ rust/integration_test/ diff --git a/.pubignore b/.pubignore new file mode 100644 index 0000000..273958a --- /dev/null +++ b/.pubignore @@ -0,0 +1,26 @@ +# Override .gitignore for pub.dev publishing. +# FRB-generated Dart bindings must be included in the published package +# so consumers don't need to run codegen themselves. + +# Exclude development/CI files +.github/ +.vscode/ +.idea/ +*.iml +*.ipr +*.iws + +# Exclude Rust source and build artifacts (compiled via cargokit at build time) +rust/target/ + +# Exclude example build artifacts +example/build/ +example/.dart_tool/ +example/android/.gradle/ +example/ios/Pods/ +example/macos/Pods/ + +# Exclude cargokit build artifacts +cargokit/build_tool/.dart_tool/ + +# Do NOT exclude lib/src/rust/ — these generated files are needed by consumers diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 899e5c9..45fe9d8 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -91,7 +91,7 @@ M-Security/ │ ├── traits.rs # Encryption, Hasher, Kdf traits │ ├── error.rs # CryptoError enum │ └── rng.rs # Random number generation -├── rust_builder/ # Rust build system integration +├── cargokit/ # Rust build system integration (Cargokit) ├── integration_test/ # Dart integration tests ├── example/ # Flutter example app └── .github/workflows/ # CI pipeline diff --git a/RELEASE_GUIDE.md b/RELEASE_GUIDE.md index 3be96d9..356df6c 100644 --- a/RELEASE_GUIDE.md +++ b/RELEASE_GUIDE.md @@ -42,11 +42,6 @@ version: X.Y.Z version = "X.Y.Z" ``` -**`rust_builder/pubspec.yaml`** (if applicable): -```yaml -version: X.Y.Z -``` - ### 3. Update CHANGELOG.md Move the `## Unreleased` section content under a new version header with the current date: diff --git a/android/build.gradle b/android/build.gradle index a0dffec..8e49ee0 100644 --- a/android/build.gradle +++ b/android/build.gradle @@ -1,66 +1,56 @@ -group = "com.example.m_security" -version = "1.0-SNAPSHOT" +// The Android Gradle Plugin builds the native code with the Android NDK. + +group 'com.flutter_rust_bridge.m_security' +version '1.0' buildscript { - ext.kotlin_version = "2.2.20" repositories { google() mavenCentral() } dependencies { - classpath("com.android.tools.build:gradle:8.11.1") - classpath("org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version") + // The Android Gradle Plugin knows how to build native code with the NDK. + classpath 'com.android.tools.build:gradle:7.3.0' } } -allprojects { +rootProject.allprojects { repositories { google() mavenCentral() } } -apply plugin: "com.android.library" -apply plugin: "kotlin-android" +apply plugin: 'com.android.library' android { - namespace = "com.example.m_security" - - compileSdk = 36 - - compileOptions { - sourceCompatibility = JavaVersion.VERSION_17 - targetCompatibility = JavaVersion.VERSION_17 + if (project.android.hasProperty("namespace")) { + namespace 'com.flutter_rust_bridge.m_security' } - kotlinOptions { - jvmTarget = JavaVersion.VERSION_17 - } + // Bumping the plugin compileSdkVersion requires all clients of this plugin + // to bump the version in their app. + compileSdkVersion 33 - sourceSets { - main.java.srcDirs += "src/main/kotlin" - test.java.srcDirs += "src/test/kotlin" - } + // Use the NDK version + // declared in /android/app/build.gradle file of the Flutter project. + // Replace it with a version number if this plugin requires a specfic NDK version. + // (e.g. ndkVersion "23.1.7779620") + ndkVersion android.ndkVersion - defaultConfig { - minSdk = 24 + compileOptions { + sourceCompatibility JavaVersion.VERSION_1_8 + targetCompatibility JavaVersion.VERSION_1_8 } - dependencies { - testImplementation("org.jetbrains.kotlin:kotlin-test") - testImplementation("org.mockito:mockito-core:5.0.0") + defaultConfig { + minSdkVersion 19 } +} - testOptions { - unitTests.all { - useJUnitPlatform() - - testLogging { - events "passed", "skipped", "failed", "standardOut", "standardError" - outputs.upToDateWhen {false} - showStandardStreams = true - } - } - } +apply from: "../cargokit/gradle/plugin.gradle" +cargokit { + manifestDir = "../rust" + libname = "rust_lib_m_security" } diff --git a/android/src/main/AndroidManifest.xml b/android/src/main/AndroidManifest.xml index 0786908..bf7a9e7 100644 --- a/android/src/main/AndroidManifest.xml +++ b/android/src/main/AndroidManifest.xml @@ -1,3 +1,3 @@ + package="com.flutter_rust_bridge.m_security"> diff --git a/android/src/main/kotlin/com/example/m_security/MSecurityPlugin.kt b/android/src/main/kotlin/com/example/m_security/MSecurityPlugin.kt deleted file mode 100644 index 38ea308..0000000 --- a/android/src/main/kotlin/com/example/m_security/MSecurityPlugin.kt +++ /dev/null @@ -1,38 +0,0 @@ -package com.example.m_security - -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 - -/** MSecurityPlugin */ -class MSecurityPlugin : - 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 - - override fun onAttachedToEngine(flutterPluginBinding: FlutterPlugin.FlutterPluginBinding) { - channel = MethodChannel(flutterPluginBinding.binaryMessenger, "m_security") - channel.setMethodCallHandler(this) - } - - override fun onMethodCall( - call: MethodCall, - result: Result - ) { - if (call.method == "getPlatformVersion") { - result.success("Android ${android.os.Build.VERSION.RELEASE}") - } else { - result.notImplemented() - } - } - - override fun onDetachedFromEngine(binding: FlutterPlugin.FlutterPluginBinding) { - channel.setMethodCallHandler(null) - } -} diff --git a/android/src/test/kotlin/com/example/m_security/MSecurityPluginTest.kt b/android/src/test/kotlin/com/example/m_security/MSecurityPluginTest.kt deleted file mode 100644 index dbd4f2b..0000000 --- a/android/src/test/kotlin/com/example/m_security/MSecurityPluginTest.kt +++ /dev/null @@ -1,27 +0,0 @@ -package com.example.m_security - -import io.flutter.plugin.common.MethodCall -import io.flutter.plugin.common.MethodChannel -import org.mockito.Mockito -import kotlin.test.Test - -/* - * This demonstrates a simple unit test of the Kotlin portion of this plugin's implementation. - * - * Once you have built the plugin's example app, you can run these tests from the command - * line by running `./gradlew testDebugUnitTest` in the `example/android/` directory, or - * you can run them directly from IDEs that support JUnit such as Android Studio. - */ - -internal class MSecurityPluginTest { - @Test - fun onMethodCall_getPlatformVersion_returnsExpectedValue() { - val plugin = MSecurityPlugin() - - val call = MethodCall("getPlatformVersion", null) - val mockResult: MethodChannel.Result = Mockito.mock(MethodChannel.Result::class.java) - plugin.onMethodCall(call, mockResult) - - Mockito.verify(mockResult).success("Android " + android.os.Build.VERSION.RELEASE) - } -} diff --git a/rust_builder/cargokit/.gitignore b/cargokit/.gitignore similarity index 100% rename from rust_builder/cargokit/.gitignore rename to cargokit/.gitignore diff --git a/rust_builder/cargokit/LICENSE b/cargokit/LICENSE similarity index 100% rename from rust_builder/cargokit/LICENSE rename to cargokit/LICENSE diff --git a/rust_builder/cargokit/README b/cargokit/README similarity index 100% rename from rust_builder/cargokit/README rename to cargokit/README diff --git a/rust_builder/cargokit/build_pod.sh b/cargokit/build_pod.sh old mode 100644 new mode 100755 similarity index 100% rename from rust_builder/cargokit/build_pod.sh rename to cargokit/build_pod.sh diff --git a/rust_builder/cargokit/build_tool/README.md b/cargokit/build_tool/README.md similarity index 100% rename from rust_builder/cargokit/build_tool/README.md rename to cargokit/build_tool/README.md diff --git a/rust_builder/cargokit/build_tool/analysis_options.yaml b/cargokit/build_tool/analysis_options.yaml similarity index 100% rename from rust_builder/cargokit/build_tool/analysis_options.yaml rename to cargokit/build_tool/analysis_options.yaml diff --git a/rust_builder/cargokit/build_tool/bin/build_tool.dart b/cargokit/build_tool/bin/build_tool.dart similarity index 100% rename from rust_builder/cargokit/build_tool/bin/build_tool.dart rename to cargokit/build_tool/bin/build_tool.dart diff --git a/rust_builder/cargokit/build_tool/lib/build_tool.dart b/cargokit/build_tool/lib/build_tool.dart similarity index 100% rename from rust_builder/cargokit/build_tool/lib/build_tool.dart rename to cargokit/build_tool/lib/build_tool.dart diff --git a/rust_builder/cargokit/build_tool/lib/src/android_environment.dart b/cargokit/build_tool/lib/src/android_environment.dart similarity index 100% rename from rust_builder/cargokit/build_tool/lib/src/android_environment.dart rename to cargokit/build_tool/lib/src/android_environment.dart diff --git a/rust_builder/cargokit/build_tool/lib/src/artifacts_provider.dart b/cargokit/build_tool/lib/src/artifacts_provider.dart similarity index 100% rename from rust_builder/cargokit/build_tool/lib/src/artifacts_provider.dart rename to cargokit/build_tool/lib/src/artifacts_provider.dart diff --git a/rust_builder/cargokit/build_tool/lib/src/build_cmake.dart b/cargokit/build_tool/lib/src/build_cmake.dart similarity index 100% rename from rust_builder/cargokit/build_tool/lib/src/build_cmake.dart rename to cargokit/build_tool/lib/src/build_cmake.dart diff --git a/rust_builder/cargokit/build_tool/lib/src/build_gradle.dart b/cargokit/build_tool/lib/src/build_gradle.dart similarity index 100% rename from rust_builder/cargokit/build_tool/lib/src/build_gradle.dart rename to cargokit/build_tool/lib/src/build_gradle.dart diff --git a/rust_builder/cargokit/build_tool/lib/src/build_pod.dart b/cargokit/build_tool/lib/src/build_pod.dart similarity index 100% rename from rust_builder/cargokit/build_tool/lib/src/build_pod.dart rename to cargokit/build_tool/lib/src/build_pod.dart diff --git a/rust_builder/cargokit/build_tool/lib/src/build_tool.dart b/cargokit/build_tool/lib/src/build_tool.dart similarity index 100% rename from rust_builder/cargokit/build_tool/lib/src/build_tool.dart rename to cargokit/build_tool/lib/src/build_tool.dart diff --git a/rust_builder/cargokit/build_tool/lib/src/builder.dart b/cargokit/build_tool/lib/src/builder.dart similarity index 100% rename from rust_builder/cargokit/build_tool/lib/src/builder.dart rename to cargokit/build_tool/lib/src/builder.dart diff --git a/rust_builder/cargokit/build_tool/lib/src/cargo.dart b/cargokit/build_tool/lib/src/cargo.dart similarity index 100% rename from rust_builder/cargokit/build_tool/lib/src/cargo.dart rename to cargokit/build_tool/lib/src/cargo.dart diff --git a/rust_builder/cargokit/build_tool/lib/src/crate_hash.dart b/cargokit/build_tool/lib/src/crate_hash.dart similarity index 100% rename from rust_builder/cargokit/build_tool/lib/src/crate_hash.dart rename to cargokit/build_tool/lib/src/crate_hash.dart diff --git a/rust_builder/cargokit/build_tool/lib/src/environment.dart b/cargokit/build_tool/lib/src/environment.dart similarity index 100% rename from rust_builder/cargokit/build_tool/lib/src/environment.dart rename to cargokit/build_tool/lib/src/environment.dart diff --git a/rust_builder/cargokit/build_tool/lib/src/logging.dart b/cargokit/build_tool/lib/src/logging.dart similarity index 100% rename from rust_builder/cargokit/build_tool/lib/src/logging.dart rename to cargokit/build_tool/lib/src/logging.dart diff --git a/rust_builder/cargokit/build_tool/lib/src/options.dart b/cargokit/build_tool/lib/src/options.dart similarity index 100% rename from rust_builder/cargokit/build_tool/lib/src/options.dart rename to cargokit/build_tool/lib/src/options.dart diff --git a/rust_builder/cargokit/build_tool/lib/src/precompile_binaries.dart b/cargokit/build_tool/lib/src/precompile_binaries.dart similarity index 100% rename from rust_builder/cargokit/build_tool/lib/src/precompile_binaries.dart rename to cargokit/build_tool/lib/src/precompile_binaries.dart diff --git a/rust_builder/cargokit/build_tool/lib/src/rustup.dart b/cargokit/build_tool/lib/src/rustup.dart similarity index 100% rename from rust_builder/cargokit/build_tool/lib/src/rustup.dart rename to cargokit/build_tool/lib/src/rustup.dart diff --git a/rust_builder/cargokit/build_tool/lib/src/target.dart b/cargokit/build_tool/lib/src/target.dart similarity index 100% rename from rust_builder/cargokit/build_tool/lib/src/target.dart rename to cargokit/build_tool/lib/src/target.dart diff --git a/rust_builder/cargokit/build_tool/lib/src/util.dart b/cargokit/build_tool/lib/src/util.dart similarity index 100% rename from rust_builder/cargokit/build_tool/lib/src/util.dart rename to cargokit/build_tool/lib/src/util.dart diff --git a/rust_builder/cargokit/build_tool/lib/src/verify_binaries.dart b/cargokit/build_tool/lib/src/verify_binaries.dart similarity index 100% rename from rust_builder/cargokit/build_tool/lib/src/verify_binaries.dart rename to cargokit/build_tool/lib/src/verify_binaries.dart diff --git a/rust_builder/cargokit/build_tool/pubspec.lock b/cargokit/build_tool/pubspec.lock similarity index 100% rename from rust_builder/cargokit/build_tool/pubspec.lock rename to cargokit/build_tool/pubspec.lock diff --git a/rust_builder/cargokit/build_tool/pubspec.yaml b/cargokit/build_tool/pubspec.yaml similarity index 100% rename from rust_builder/cargokit/build_tool/pubspec.yaml rename to cargokit/build_tool/pubspec.yaml diff --git a/rust_builder/cargokit/cmake/cargokit.cmake b/cargokit/cmake/cargokit.cmake similarity index 100% rename from rust_builder/cargokit/cmake/cargokit.cmake rename to cargokit/cmake/cargokit.cmake diff --git a/rust_builder/cargokit/cmake/resolve_symlinks.ps1 b/cargokit/cmake/resolve_symlinks.ps1 similarity index 100% rename from rust_builder/cargokit/cmake/resolve_symlinks.ps1 rename to cargokit/cmake/resolve_symlinks.ps1 diff --git a/rust_builder/cargokit/gradle/plugin.gradle b/cargokit/gradle/plugin.gradle similarity index 100% rename from rust_builder/cargokit/gradle/plugin.gradle rename to cargokit/gradle/plugin.gradle diff --git a/rust_builder/cargokit/run_build_tool.cmd b/cargokit/run_build_tool.cmd similarity index 100% rename from rust_builder/cargokit/run_build_tool.cmd rename to cargokit/run_build_tool.cmd diff --git a/rust_builder/cargokit/run_build_tool.sh b/cargokit/run_build_tool.sh similarity index 100% rename from rust_builder/cargokit/run_build_tool.sh rename to cargokit/run_build_tool.sh diff --git a/example/ios/RunnerTests/RunnerTests.swift b/example/ios/RunnerTests/RunnerTests.swift index f5e7aad..ce52b7f 100644 --- a/example/ios/RunnerTests/RunnerTests.swift +++ b/example/ios/RunnerTests/RunnerTests.swift @@ -1,27 +1,11 @@ -import Flutter -import UIKit import XCTest - -@testable import m_security - -// This demonstrates a simple unit test of the Swift portion of this plugin's implementation. -// -// See https://developer.apple.com/documentation/xctest for more information about using XCTest. - class RunnerTests: XCTestCase { - func testGetPlatformVersion() { - let plugin = MSecurityPlugin() - - let call = FlutterMethodCall(methodName: "getPlatformVersion", arguments: []) - - let resultExpectation = expectation(description: "result block must be called.") - plugin.handle(call) { result in - XCTAssertEqual(result as! String, "iOS " + UIDevice.current.systemVersion) - resultExpectation.fulfill() - } - waitForExpectations(timeout: 1) + func testPluginLoads() { + // M-Security uses FFI (not method channels), so there is no Swift plugin class to test. + // Cryptographic functionality is validated via Dart integration tests. + XCTAssertTrue(true) } } diff --git a/example/linux/flutter/generated_plugin_registrant.cc b/example/linux/flutter/generated_plugin_registrant.cc index e57007a..e71a16d 100644 --- a/example/linux/flutter/generated_plugin_registrant.cc +++ b/example/linux/flutter/generated_plugin_registrant.cc @@ -6,10 +6,6 @@ #include "generated_plugin_registrant.h" -#include void fl_register_plugins(FlPluginRegistry* registry) { - g_autoptr(FlPluginRegistrar) m_security_registrar = - fl_plugin_registry_get_registrar_for_plugin(registry, "MSecurityPlugin"); - m_security_plugin_register_with_registrar(m_security_registrar); } diff --git a/example/linux/flutter/generated_plugins.cmake b/example/linux/flutter/generated_plugins.cmake index 2d4719a..e944791 100644 --- a/example/linux/flutter/generated_plugins.cmake +++ b/example/linux/flutter/generated_plugins.cmake @@ -3,11 +3,10 @@ # list(APPEND FLUTTER_PLUGIN_LIST - m_security ) list(APPEND FLUTTER_FFI_PLUGIN_LIST - rust_lib_m_security + m_security ) set(PLUGIN_BUNDLED_LIBRARIES) diff --git a/example/macos/Flutter/GeneratedPluginRegistrant.swift b/example/macos/Flutter/GeneratedPluginRegistrant.swift index 28e08bd..cccf817 100644 --- a/example/macos/Flutter/GeneratedPluginRegistrant.swift +++ b/example/macos/Flutter/GeneratedPluginRegistrant.swift @@ -5,8 +5,6 @@ import FlutterMacOS import Foundation -import m_security func RegisterGeneratedPlugins(registry: FlutterPluginRegistry) { - MSecurityPlugin.register(with: registry.registrar(forPlugin: "MSecurityPlugin")) } diff --git a/example/macos/RunnerTests/RunnerTests.swift b/example/macos/RunnerTests/RunnerTests.swift index 73df93e..ce52b7f 100644 --- a/example/macos/RunnerTests/RunnerTests.swift +++ b/example/macos/RunnerTests/RunnerTests.swift @@ -1,28 +1,11 @@ -import Cocoa -import FlutterMacOS import XCTest - -@testable import m_security - -// This demonstrates a simple unit test of the Swift portion of this plugin's implementation. -// -// See https://developer.apple.com/documentation/xctest for more information about using XCTest. - class RunnerTests: XCTestCase { - func testGetPlatformVersion() { - let plugin = MSecurityPlugin() - - let call = FlutterMethodCall(methodName: "getPlatformVersion", arguments: []) - - let resultExpectation = expectation(description: "result block must be called.") - plugin.handle(call) { result in - XCTAssertEqual(result as! String, - "macOS " + ProcessInfo.processInfo.operatingSystemVersionString) - resultExpectation.fulfill() - } - waitForExpectations(timeout: 1) + func testPluginLoads() { + // M-Security uses FFI (not method channels), so there is no Swift plugin class to test. + // Cryptographic functionality is validated via Dart integration tests. + XCTAssertTrue(true) } } diff --git a/example/pubspec.lock b/example/pubspec.lock index c0f007a..7ce72f1 100644 --- a/example/pubspec.lock +++ b/example/pubspec.lock @@ -233,13 +233,6 @@ packages: url: "https://pub.dev" source: hosted version: "5.0.5" - rust_lib_m_security: - dependency: transitive - description: - path: "../rust_builder" - relative: true - source: path - version: "0.0.1" sky_engine: dependency: transitive description: flutter diff --git a/example/windows/flutter/generated_plugin_registrant.cc b/example/windows/flutter/generated_plugin_registrant.cc index 99012dc..8b6d468 100644 --- a/example/windows/flutter/generated_plugin_registrant.cc +++ b/example/windows/flutter/generated_plugin_registrant.cc @@ -6,9 +6,6 @@ #include "generated_plugin_registrant.h" -#include void RegisterPlugins(flutter::PluginRegistry* registry) { - MSecurityPluginCApiRegisterWithRegistrar( - registry->GetRegistrarForPlugin("MSecurityPluginCApi")); } diff --git a/example/windows/flutter/generated_plugins.cmake b/example/windows/flutter/generated_plugins.cmake index 59fca2c..8be7a76 100644 --- a/example/windows/flutter/generated_plugins.cmake +++ b/example/windows/flutter/generated_plugins.cmake @@ -3,11 +3,10 @@ # list(APPEND FLUTTER_PLUGIN_LIST - m_security ) list(APPEND FLUTTER_FFI_PLUGIN_LIST - rust_lib_m_security + m_security ) set(PLUGIN_BUNDLED_LIBRARIES) diff --git a/ios/Classes/MSecurityPlugin.swift b/ios/Classes/MSecurityPlugin.swift deleted file mode 100644 index ada2b35..0000000 --- a/ios/Classes/MSecurityPlugin.swift +++ /dev/null @@ -1,19 +0,0 @@ -import Flutter -import UIKit - -public class MSecurityPlugin: NSObject, FlutterPlugin { - public static func register(with registrar: FlutterPluginRegistrar) { - let channel = FlutterMethodChannel(name: "m_security", binaryMessenger: registrar.messenger()) - let instance = MSecurityPlugin() - registrar.addMethodCallDelegate(instance, channel: channel) - } - - public func handle(_ call: FlutterMethodCall, result: @escaping FlutterResult) { - switch call.method { - case "getPlatformVersion": - result("iOS " + UIDevice.current.systemVersion) - default: - result(FlutterMethodNotImplemented) - } - } -} diff --git a/rust_builder/ios/Classes/dummy_file.c b/ios/Classes/dummy_file.c similarity index 100% rename from rust_builder/ios/Classes/dummy_file.c rename to ios/Classes/dummy_file.c diff --git a/ios/m_security.podspec b/ios/m_security.podspec index 5d3900b..21cd413 100644 --- a/ios/m_security.podspec +++ b/ios/m_security.podspec @@ -5,25 +5,43 @@ Pod::Spec.new do |s| s.name = 'm_security' s.version = '0.0.1' - s.summary = 'A new Flutter plugin project.' + s.summary = 'A high-performance cryptographic SDK for Flutter powered by native Rust via FFI.' s.description = <<-DESC -A new Flutter plugin project. +A high-performance cryptographic SDK for Flutter powered by native Rust via FFI. +Provides authenticated encryption (AES-256-GCM, ChaCha20-Poly1305), modern hashing +(BLAKE3, SHA-3, Argon2id), and key derivation (HKDF-SHA256) with secure memory management. DESC - s.homepage = 'http://example.com' + s.homepage = 'https://github.com/MicroClub-USTHB/M-Security' s.license = { :file => '../LICENSE' } - s.author = { 'Your Company' => 'email@example.com' } + s.author = { 'MicroClub-USTHB' => 'https://github.com/MicroClub-USTHB' } + + # This will ensure the source files in Classes/ are included in the native + # builds of apps using this FFI plugin. Podspec does not support relative + # paths, so Classes contains a forwarder C file that relatively imports + # `../src/*` so that the C sources can be shared among all target platforms. s.source = { :path => '.' } s.source_files = 'Classes/**/*' s.dependency 'Flutter' - s.platform = :ios, '13.0' + s.platform = :ios, '11.0' # Flutter.framework does not contain a i386 slice. s.pod_target_xcconfig = { 'DEFINES_MODULE' => 'YES', 'EXCLUDED_ARCHS[sdk=iphonesimulator*]' => 'i386' } s.swift_version = '5.0' - # If your plugin requires a privacy manifest, for example if it uses any - # required reason APIs, update the PrivacyInfo.xcprivacy file to describe your - # plugin's privacy impact, and then uncomment this line. For more information, - # see https://developer.apple.com/documentation/bundleresources/privacy_manifest_files - # s.resource_bundles = {'m_security_privacy' => ['Resources/PrivacyInfo.xcprivacy']} + s.script_phase = { + :name => 'Build Rust library', + # First argument is relative path to the `rust` folder, second is name of rust library + :script => 'sh "$PODS_TARGET_SRCROOT/../cargokit/build_pod.sh" ../rust rust_lib_m_security', + :execution_position => :before_compile, + :input_files => ['${BUILT_PRODUCTS_DIR}/cargokit_phony'], + # Let XCode know that the static library referenced in -force_load below is + # created by this build step. + :output_files => ["${BUILT_PRODUCTS_DIR}/librust_lib_m_security.a"], + } + s.pod_target_xcconfig = { + 'DEFINES_MODULE' => 'YES', + # Flutter.framework does not contain a i386 slice. + 'EXCLUDED_ARCHS[sdk=iphonesimulator*]' => 'i386', + 'OTHER_LDFLAGS' => '-force_load ${BUILT_PRODUCTS_DIR}/librust_lib_m_security.a', + } end diff --git a/lib/src/rust/api/hashing.dart b/lib/src/rust/api/hashing.dart new file mode 100644 index 0000000..40a78c7 --- /dev/null +++ b/lib/src/rust/api/hashing.dart @@ -0,0 +1,54 @@ +// This file is automatically generated, so please do not edit it. +// @generated by `flutter_rust_bridge`@ 2.11.1. + +// ignore_for_file: invalid_use_of_internal_member, unused_import, unnecessary_import + +import '../core/error.dart'; +import '../frb_generated.dart'; +import 'package:flutter_rust_bridge/flutter_rust_bridge_for_generated.dart'; + +// These functions are ignored because they are not marked as `pub`: `new` + +/// Create a BLAKE3 hasher handle. +Future createBlake3() => + RustLib.instance.api.crateApiHashingCreateBlake3(); + +/// Create a SHA-3 hasher handle. +Future createSha3() => + RustLib.instance.api.crateApiHashingCreateSha3(); + +/// Feed data into the hasher. +Future hasherUpdate({ + required HasherHandle handle, + required List data, +}) => RustLib.instance.api.crateApiHashingHasherUpdate( + handle: handle, + data: data, +); + +/// Reset the hasher to its initial state. +Future hasherReset({required HasherHandle handle}) => + RustLib.instance.api.crateApiHashingHasherReset(handle: handle); + +/// Finalize and return the digest. +Future hasherFinalize({required HasherHandle handle}) => + RustLib.instance.api.crateApiHashingHasherFinalize(handle: handle); + +/// Get the algorithm identifier for the hasher. +Future hasherAlgorithmId({required HasherHandle handle}) => + RustLib.instance.api.crateApiHashingHasherAlgorithmId(handle: handle); + +/// One-shot BLAKE3 hash function. +/// +/// Convenience function for hashing data in a single call. +Future blake3Hash({required List data}) => + RustLib.instance.api.crateApiHashingBlake3Hash(data: data); + +/// One-shot SHA-3 hash function. +/// +/// Convenience function for hashing data in a single call. +Future sha3Hash({required List data}) => + RustLib.instance.api.crateApiHashingSha3Hash(data: data); + +// Rust type: RustOpaqueMoi> +abstract class HasherHandle implements RustOpaqueInterface {} diff --git a/lib/src/rust/api/hashing/argon2.dart b/lib/src/rust/api/hashing/argon2.dart new file mode 100644 index 0000000..791652a --- /dev/null +++ b/lib/src/rust/api/hashing/argon2.dart @@ -0,0 +1,57 @@ +// This file is automatically generated, so please do not edit it. +// @generated by `flutter_rust_bridge`@ 2.11.1. + +// ignore_for_file: invalid_use_of_internal_member, unused_import, unnecessary_import + +import '../../core/error.dart'; +import '../../frb_generated.dart'; +import 'package:flutter_rust_bridge/flutter_rust_bridge_for_generated.dart'; + +// These functions are ignored because they are not marked as `pub`: `params` + +/// Hash a password using Argon2id with the given preset. +/// +/// Generates a random salt internally and returns a PHC-format string +/// containing the algorithm, parameters, salt, and hash. +Future argon2IdHash({ + required String password, + required Argon2Preset preset, +}) => RustLib.instance.api.crateApiHashingArgon2Argon2IdHash( + password: password, + preset: preset, +); + +/// Hash a password using Argon2id with an explicit salt. +/// +/// The salt must be valid base64 (no padding), between 1-64 bytes decoded. +/// Returns a PHC-format string. +Future argon2IdHashWithSalt({ + required String password, + required String salt, + required Argon2Preset preset, +}) => RustLib.instance.api.crateApiHashingArgon2Argon2IdHashWithSalt( + password: password, + salt: salt, + preset: preset, +); + +/// Verify a password against an Argon2id PHC hash string. +/// +/// Returns `Ok(())` if the password matches, or +/// `Err(CryptoError::AuthenticationFailed)` if it does not. +Future argon2IdVerify({ + required String phcHash, + required String password, +}) => RustLib.instance.api.crateApiHashingArgon2Argon2IdVerify( + phcHash: phcHash, + password: password, +); + +/// Platform-appropriate parameter presets for Argon2id. +enum Argon2Preset { + /// Optimized for mobile devices (64 MiB, 3 iterations, 4 threads). + mobile, + + /// Optimized for desktop/server (256 MiB, 4 iterations, 8 threads). + desktop, +} diff --git a/lib/src/rust/core/error.dart b/lib/src/rust/core/error.dart new file mode 100644 index 0000000..f048163 --- /dev/null +++ b/lib/src/rust/core/error.dart @@ -0,0 +1,31 @@ +// This file is automatically generated, so please do not edit it. +// @generated by `flutter_rust_bridge`@ 2.11.1. + +// ignore_for_file: invalid_use_of_internal_member, unused_import, unnecessary_import + +import '../frb_generated.dart'; +import 'package:flutter_rust_bridge/flutter_rust_bridge_for_generated.dart'; +import 'package:freezed_annotation/freezed_annotation.dart' hide protected; +part 'error.freezed.dart'; + +@freezed +sealed class CryptoError with _$CryptoError implements FrbException { + const CryptoError._(); + + const factory CryptoError.invalidKeyLength({ + required BigInt expected, + required BigInt actual, + }) = CryptoError_InvalidKeyLength; + const factory CryptoError.invalidNonce() = CryptoError_InvalidNonce; + const factory CryptoError.encryptionFailed(String field0) = + CryptoError_EncryptionFailed; + const factory CryptoError.decryptionFailed() = CryptoError_DecryptionFailed; + const factory CryptoError.hashingFailed(String field0) = + CryptoError_HashingFailed; + const factory CryptoError.kdfFailed(String field0) = CryptoError_KdfFailed; + const factory CryptoError.ioError(String field0) = CryptoError_IoError; + const factory CryptoError.invalidParameter(String field0) = + CryptoError_InvalidParameter; + const factory CryptoError.authenticationFailed() = + CryptoError_AuthenticationFailed; +} diff --git a/lib/src/rust/core/error.freezed.dart b/lib/src/rust/core/error.freezed.dart new file mode 100644 index 0000000..6eaffbd --- /dev/null +++ b/lib/src/rust/core/error.freezed.dart @@ -0,0 +1,710 @@ +// GENERATED CODE - DO NOT MODIFY BY HAND +// coverage:ignore-file +// ignore_for_file: type=lint +// ignore_for_file: unused_element, deprecated_member_use, deprecated_member_use_from_same_package, use_function_type_syntax_for_parameters, unnecessary_const, avoid_init_to_null, invalid_override_different_default_values_named, prefer_expression_function_bodies, annotate_overrides, invalid_annotation_target, unnecessary_question_mark + +part of 'error.dart'; + +// ************************************************************************** +// FreezedGenerator +// ************************************************************************** + +// dart format off +T _$identity(T value) => value; +/// @nodoc +mixin _$CryptoError { + + + + + +@override +bool operator ==(Object other) { + return identical(this, other) || (other.runtimeType == runtimeType&&other is CryptoError); +} + + +@override +int get hashCode => runtimeType.hashCode; + +@override +String toString() { + return 'CryptoError()'; +} + + +} + +/// @nodoc +class $CryptoErrorCopyWith<$Res> { +$CryptoErrorCopyWith(CryptoError _, $Res Function(CryptoError) __); +} + + +/// Adds pattern-matching-related methods to [CryptoError]. +extension CryptoErrorPatterns on CryptoError { +/// A variant of `map` that fallback to returning `orElse`. +/// +/// It is equivalent to doing: +/// ```dart +/// switch (sealedClass) { +/// case final Subclass value: +/// return ...; +/// case _: +/// return orElse(); +/// } +/// ``` + +@optionalTypeArgs TResult maybeMap({TResult Function( CryptoError_InvalidKeyLength value)? invalidKeyLength,TResult Function( CryptoError_InvalidNonce value)? invalidNonce,TResult Function( CryptoError_EncryptionFailed value)? encryptionFailed,TResult Function( CryptoError_DecryptionFailed value)? decryptionFailed,TResult Function( CryptoError_HashingFailed value)? hashingFailed,TResult Function( CryptoError_KdfFailed value)? kdfFailed,TResult Function( CryptoError_IoError value)? ioError,TResult Function( CryptoError_InvalidParameter value)? invalidParameter,TResult Function( CryptoError_AuthenticationFailed value)? authenticationFailed,required TResult orElse(),}){ +final _that = this; +switch (_that) { +case CryptoError_InvalidKeyLength() when invalidKeyLength != null: +return invalidKeyLength(_that);case CryptoError_InvalidNonce() when invalidNonce != null: +return invalidNonce(_that);case CryptoError_EncryptionFailed() when encryptionFailed != null: +return encryptionFailed(_that);case CryptoError_DecryptionFailed() when decryptionFailed != null: +return decryptionFailed(_that);case CryptoError_HashingFailed() when hashingFailed != null: +return hashingFailed(_that);case CryptoError_KdfFailed() when kdfFailed != null: +return kdfFailed(_that);case CryptoError_IoError() when ioError != null: +return ioError(_that);case CryptoError_InvalidParameter() when invalidParameter != null: +return invalidParameter(_that);case CryptoError_AuthenticationFailed() when authenticationFailed != null: +return authenticationFailed(_that);case _: + return orElse(); + +} +} +/// A `switch`-like method, using callbacks. +/// +/// Callbacks receives the raw object, upcasted. +/// It is equivalent to doing: +/// ```dart +/// switch (sealedClass) { +/// case final Subclass value: +/// return ...; +/// case final Subclass2 value: +/// return ...; +/// } +/// ``` + +@optionalTypeArgs TResult map({required TResult Function( CryptoError_InvalidKeyLength value) invalidKeyLength,required TResult Function( CryptoError_InvalidNonce value) invalidNonce,required TResult Function( CryptoError_EncryptionFailed value) encryptionFailed,required TResult Function( CryptoError_DecryptionFailed value) decryptionFailed,required TResult Function( CryptoError_HashingFailed value) hashingFailed,required TResult Function( CryptoError_KdfFailed value) kdfFailed,required TResult Function( CryptoError_IoError value) ioError,required TResult Function( CryptoError_InvalidParameter value) invalidParameter,required TResult Function( CryptoError_AuthenticationFailed value) authenticationFailed,}){ +final _that = this; +switch (_that) { +case CryptoError_InvalidKeyLength(): +return invalidKeyLength(_that);case CryptoError_InvalidNonce(): +return invalidNonce(_that);case CryptoError_EncryptionFailed(): +return encryptionFailed(_that);case CryptoError_DecryptionFailed(): +return decryptionFailed(_that);case CryptoError_HashingFailed(): +return hashingFailed(_that);case CryptoError_KdfFailed(): +return kdfFailed(_that);case CryptoError_IoError(): +return ioError(_that);case CryptoError_InvalidParameter(): +return invalidParameter(_that);case CryptoError_AuthenticationFailed(): +return authenticationFailed(_that);} +} +/// A variant of `map` that fallback to returning `null`. +/// +/// It is equivalent to doing: +/// ```dart +/// switch (sealedClass) { +/// case final Subclass value: +/// return ...; +/// case _: +/// return null; +/// } +/// ``` + +@optionalTypeArgs TResult? mapOrNull({TResult? Function( CryptoError_InvalidKeyLength value)? invalidKeyLength,TResult? Function( CryptoError_InvalidNonce value)? invalidNonce,TResult? Function( CryptoError_EncryptionFailed value)? encryptionFailed,TResult? Function( CryptoError_DecryptionFailed value)? decryptionFailed,TResult? Function( CryptoError_HashingFailed value)? hashingFailed,TResult? Function( CryptoError_KdfFailed value)? kdfFailed,TResult? Function( CryptoError_IoError value)? ioError,TResult? Function( CryptoError_InvalidParameter value)? invalidParameter,TResult? Function( CryptoError_AuthenticationFailed value)? authenticationFailed,}){ +final _that = this; +switch (_that) { +case CryptoError_InvalidKeyLength() when invalidKeyLength != null: +return invalidKeyLength(_that);case CryptoError_InvalidNonce() when invalidNonce != null: +return invalidNonce(_that);case CryptoError_EncryptionFailed() when encryptionFailed != null: +return encryptionFailed(_that);case CryptoError_DecryptionFailed() when decryptionFailed != null: +return decryptionFailed(_that);case CryptoError_HashingFailed() when hashingFailed != null: +return hashingFailed(_that);case CryptoError_KdfFailed() when kdfFailed != null: +return kdfFailed(_that);case CryptoError_IoError() when ioError != null: +return ioError(_that);case CryptoError_InvalidParameter() when invalidParameter != null: +return invalidParameter(_that);case CryptoError_AuthenticationFailed() when authenticationFailed != null: +return authenticationFailed(_that);case _: + return null; + +} +} +/// A variant of `when` that fallback to an `orElse` callback. +/// +/// It is equivalent to doing: +/// ```dart +/// switch (sealedClass) { +/// case Subclass(:final field): +/// return ...; +/// case _: +/// return orElse(); +/// } +/// ``` + +@optionalTypeArgs TResult maybeWhen({TResult Function( BigInt expected, BigInt actual)? invalidKeyLength,TResult Function()? invalidNonce,TResult Function( String field0)? encryptionFailed,TResult Function()? decryptionFailed,TResult Function( String field0)? hashingFailed,TResult Function( String field0)? kdfFailed,TResult Function( String field0)? ioError,TResult Function( String field0)? invalidParameter,TResult Function()? authenticationFailed,required TResult orElse(),}) {final _that = this; +switch (_that) { +case CryptoError_InvalidKeyLength() when invalidKeyLength != null: +return invalidKeyLength(_that.expected,_that.actual);case CryptoError_InvalidNonce() when invalidNonce != null: +return invalidNonce();case CryptoError_EncryptionFailed() when encryptionFailed != null: +return encryptionFailed(_that.field0);case CryptoError_DecryptionFailed() when decryptionFailed != null: +return decryptionFailed();case CryptoError_HashingFailed() when hashingFailed != null: +return hashingFailed(_that.field0);case CryptoError_KdfFailed() when kdfFailed != null: +return kdfFailed(_that.field0);case CryptoError_IoError() when ioError != null: +return ioError(_that.field0);case CryptoError_InvalidParameter() when invalidParameter != null: +return invalidParameter(_that.field0);case CryptoError_AuthenticationFailed() when authenticationFailed != null: +return authenticationFailed();case _: + return orElse(); + +} +} +/// A `switch`-like method, using callbacks. +/// +/// As opposed to `map`, this offers destructuring. +/// It is equivalent to doing: +/// ```dart +/// switch (sealedClass) { +/// case Subclass(:final field): +/// return ...; +/// case Subclass2(:final field2): +/// return ...; +/// } +/// ``` + +@optionalTypeArgs TResult when({required TResult Function( BigInt expected, BigInt actual) invalidKeyLength,required TResult Function() invalidNonce,required TResult Function( String field0) encryptionFailed,required TResult Function() decryptionFailed,required TResult Function( String field0) hashingFailed,required TResult Function( String field0) kdfFailed,required TResult Function( String field0) ioError,required TResult Function( String field0) invalidParameter,required TResult Function() authenticationFailed,}) {final _that = this; +switch (_that) { +case CryptoError_InvalidKeyLength(): +return invalidKeyLength(_that.expected,_that.actual);case CryptoError_InvalidNonce(): +return invalidNonce();case CryptoError_EncryptionFailed(): +return encryptionFailed(_that.field0);case CryptoError_DecryptionFailed(): +return decryptionFailed();case CryptoError_HashingFailed(): +return hashingFailed(_that.field0);case CryptoError_KdfFailed(): +return kdfFailed(_that.field0);case CryptoError_IoError(): +return ioError(_that.field0);case CryptoError_InvalidParameter(): +return invalidParameter(_that.field0);case CryptoError_AuthenticationFailed(): +return authenticationFailed();} +} +/// A variant of `when` that fallback to returning `null` +/// +/// It is equivalent to doing: +/// ```dart +/// switch (sealedClass) { +/// case Subclass(:final field): +/// return ...; +/// case _: +/// return null; +/// } +/// ``` + +@optionalTypeArgs TResult? whenOrNull({TResult? Function( BigInt expected, BigInt actual)? invalidKeyLength,TResult? Function()? invalidNonce,TResult? Function( String field0)? encryptionFailed,TResult? Function()? decryptionFailed,TResult? Function( String field0)? hashingFailed,TResult? Function( String field0)? kdfFailed,TResult? Function( String field0)? ioError,TResult? Function( String field0)? invalidParameter,TResult? Function()? authenticationFailed,}) {final _that = this; +switch (_that) { +case CryptoError_InvalidKeyLength() when invalidKeyLength != null: +return invalidKeyLength(_that.expected,_that.actual);case CryptoError_InvalidNonce() when invalidNonce != null: +return invalidNonce();case CryptoError_EncryptionFailed() when encryptionFailed != null: +return encryptionFailed(_that.field0);case CryptoError_DecryptionFailed() when decryptionFailed != null: +return decryptionFailed();case CryptoError_HashingFailed() when hashingFailed != null: +return hashingFailed(_that.field0);case CryptoError_KdfFailed() when kdfFailed != null: +return kdfFailed(_that.field0);case CryptoError_IoError() when ioError != null: +return ioError(_that.field0);case CryptoError_InvalidParameter() when invalidParameter != null: +return invalidParameter(_that.field0);case CryptoError_AuthenticationFailed() when authenticationFailed != null: +return authenticationFailed();case _: + return null; + +} +} + +} + +/// @nodoc + + +class CryptoError_InvalidKeyLength extends CryptoError { + const CryptoError_InvalidKeyLength({required this.expected, required this.actual}): super._(); + + + final BigInt expected; + final BigInt actual; + +/// Create a copy of CryptoError +/// with the given fields replaced by the non-null parameter values. +@JsonKey(includeFromJson: false, includeToJson: false) +@pragma('vm:prefer-inline') +$CryptoError_InvalidKeyLengthCopyWith get copyWith => _$CryptoError_InvalidKeyLengthCopyWithImpl(this, _$identity); + + + +@override +bool operator ==(Object other) { + return identical(this, other) || (other.runtimeType == runtimeType&&other is CryptoError_InvalidKeyLength&&(identical(other.expected, expected) || other.expected == expected)&&(identical(other.actual, actual) || other.actual == actual)); +} + + +@override +int get hashCode => Object.hash(runtimeType,expected,actual); + +@override +String toString() { + return 'CryptoError.invalidKeyLength(expected: $expected, actual: $actual)'; +} + + +} + +/// @nodoc +abstract mixin class $CryptoError_InvalidKeyLengthCopyWith<$Res> implements $CryptoErrorCopyWith<$Res> { + factory $CryptoError_InvalidKeyLengthCopyWith(CryptoError_InvalidKeyLength value, $Res Function(CryptoError_InvalidKeyLength) _then) = _$CryptoError_InvalidKeyLengthCopyWithImpl; +@useResult +$Res call({ + BigInt expected, BigInt actual +}); + + + + +} +/// @nodoc +class _$CryptoError_InvalidKeyLengthCopyWithImpl<$Res> + implements $CryptoError_InvalidKeyLengthCopyWith<$Res> { + _$CryptoError_InvalidKeyLengthCopyWithImpl(this._self, this._then); + + final CryptoError_InvalidKeyLength _self; + final $Res Function(CryptoError_InvalidKeyLength) _then; + +/// Create a copy of CryptoError +/// with the given fields replaced by the non-null parameter values. +@pragma('vm:prefer-inline') $Res call({Object? expected = null,Object? actual = null,}) { + return _then(CryptoError_InvalidKeyLength( +expected: null == expected ? _self.expected : expected // ignore: cast_nullable_to_non_nullable +as BigInt,actual: null == actual ? _self.actual : actual // ignore: cast_nullable_to_non_nullable +as BigInt, + )); +} + + +} + +/// @nodoc + + +class CryptoError_InvalidNonce extends CryptoError { + const CryptoError_InvalidNonce(): super._(); + + + + + + + +@override +bool operator ==(Object other) { + return identical(this, other) || (other.runtimeType == runtimeType&&other is CryptoError_InvalidNonce); +} + + +@override +int get hashCode => runtimeType.hashCode; + +@override +String toString() { + return 'CryptoError.invalidNonce()'; +} + + +} + + + + +/// @nodoc + + +class CryptoError_EncryptionFailed extends CryptoError { + const CryptoError_EncryptionFailed(this.field0): super._(); + + + final String field0; + +/// Create a copy of CryptoError +/// with the given fields replaced by the non-null parameter values. +@JsonKey(includeFromJson: false, includeToJson: false) +@pragma('vm:prefer-inline') +$CryptoError_EncryptionFailedCopyWith get copyWith => _$CryptoError_EncryptionFailedCopyWithImpl(this, _$identity); + + + +@override +bool operator ==(Object other) { + return identical(this, other) || (other.runtimeType == runtimeType&&other is CryptoError_EncryptionFailed&&(identical(other.field0, field0) || other.field0 == field0)); +} + + +@override +int get hashCode => Object.hash(runtimeType,field0); + +@override +String toString() { + return 'CryptoError.encryptionFailed(field0: $field0)'; +} + + +} + +/// @nodoc +abstract mixin class $CryptoError_EncryptionFailedCopyWith<$Res> implements $CryptoErrorCopyWith<$Res> { + factory $CryptoError_EncryptionFailedCopyWith(CryptoError_EncryptionFailed value, $Res Function(CryptoError_EncryptionFailed) _then) = _$CryptoError_EncryptionFailedCopyWithImpl; +@useResult +$Res call({ + String field0 +}); + + + + +} +/// @nodoc +class _$CryptoError_EncryptionFailedCopyWithImpl<$Res> + implements $CryptoError_EncryptionFailedCopyWith<$Res> { + _$CryptoError_EncryptionFailedCopyWithImpl(this._self, this._then); + + final CryptoError_EncryptionFailed _self; + final $Res Function(CryptoError_EncryptionFailed) _then; + +/// Create a copy of CryptoError +/// with the given fields replaced by the non-null parameter values. +@pragma('vm:prefer-inline') $Res call({Object? field0 = null,}) { + return _then(CryptoError_EncryptionFailed( +null == field0 ? _self.field0 : field0 // ignore: cast_nullable_to_non_nullable +as String, + )); +} + + +} + +/// @nodoc + + +class CryptoError_DecryptionFailed extends CryptoError { + const CryptoError_DecryptionFailed(): super._(); + + + + + + + +@override +bool operator ==(Object other) { + return identical(this, other) || (other.runtimeType == runtimeType&&other is CryptoError_DecryptionFailed); +} + + +@override +int get hashCode => runtimeType.hashCode; + +@override +String toString() { + return 'CryptoError.decryptionFailed()'; +} + + +} + + + + +/// @nodoc + + +class CryptoError_HashingFailed extends CryptoError { + const CryptoError_HashingFailed(this.field0): super._(); + + + final String field0; + +/// Create a copy of CryptoError +/// with the given fields replaced by the non-null parameter values. +@JsonKey(includeFromJson: false, includeToJson: false) +@pragma('vm:prefer-inline') +$CryptoError_HashingFailedCopyWith get copyWith => _$CryptoError_HashingFailedCopyWithImpl(this, _$identity); + + + +@override +bool operator ==(Object other) { + return identical(this, other) || (other.runtimeType == runtimeType&&other is CryptoError_HashingFailed&&(identical(other.field0, field0) || other.field0 == field0)); +} + + +@override +int get hashCode => Object.hash(runtimeType,field0); + +@override +String toString() { + return 'CryptoError.hashingFailed(field0: $field0)'; +} + + +} + +/// @nodoc +abstract mixin class $CryptoError_HashingFailedCopyWith<$Res> implements $CryptoErrorCopyWith<$Res> { + factory $CryptoError_HashingFailedCopyWith(CryptoError_HashingFailed value, $Res Function(CryptoError_HashingFailed) _then) = _$CryptoError_HashingFailedCopyWithImpl; +@useResult +$Res call({ + String field0 +}); + + + + +} +/// @nodoc +class _$CryptoError_HashingFailedCopyWithImpl<$Res> + implements $CryptoError_HashingFailedCopyWith<$Res> { + _$CryptoError_HashingFailedCopyWithImpl(this._self, this._then); + + final CryptoError_HashingFailed _self; + final $Res Function(CryptoError_HashingFailed) _then; + +/// Create a copy of CryptoError +/// with the given fields replaced by the non-null parameter values. +@pragma('vm:prefer-inline') $Res call({Object? field0 = null,}) { + return _then(CryptoError_HashingFailed( +null == field0 ? _self.field0 : field0 // ignore: cast_nullable_to_non_nullable +as String, + )); +} + + +} + +/// @nodoc + + +class CryptoError_KdfFailed extends CryptoError { + const CryptoError_KdfFailed(this.field0): super._(); + + + final String field0; + +/// Create a copy of CryptoError +/// with the given fields replaced by the non-null parameter values. +@JsonKey(includeFromJson: false, includeToJson: false) +@pragma('vm:prefer-inline') +$CryptoError_KdfFailedCopyWith get copyWith => _$CryptoError_KdfFailedCopyWithImpl(this, _$identity); + + + +@override +bool operator ==(Object other) { + return identical(this, other) || (other.runtimeType == runtimeType&&other is CryptoError_KdfFailed&&(identical(other.field0, field0) || other.field0 == field0)); +} + + +@override +int get hashCode => Object.hash(runtimeType,field0); + +@override +String toString() { + return 'CryptoError.kdfFailed(field0: $field0)'; +} + + +} + +/// @nodoc +abstract mixin class $CryptoError_KdfFailedCopyWith<$Res> implements $CryptoErrorCopyWith<$Res> { + factory $CryptoError_KdfFailedCopyWith(CryptoError_KdfFailed value, $Res Function(CryptoError_KdfFailed) _then) = _$CryptoError_KdfFailedCopyWithImpl; +@useResult +$Res call({ + String field0 +}); + + + + +} +/// @nodoc +class _$CryptoError_KdfFailedCopyWithImpl<$Res> + implements $CryptoError_KdfFailedCopyWith<$Res> { + _$CryptoError_KdfFailedCopyWithImpl(this._self, this._then); + + final CryptoError_KdfFailed _self; + final $Res Function(CryptoError_KdfFailed) _then; + +/// Create a copy of CryptoError +/// with the given fields replaced by the non-null parameter values. +@pragma('vm:prefer-inline') $Res call({Object? field0 = null,}) { + return _then(CryptoError_KdfFailed( +null == field0 ? _self.field0 : field0 // ignore: cast_nullable_to_non_nullable +as String, + )); +} + + +} + +/// @nodoc + + +class CryptoError_IoError extends CryptoError { + const CryptoError_IoError(this.field0): super._(); + + + final String field0; + +/// Create a copy of CryptoError +/// with the given fields replaced by the non-null parameter values. +@JsonKey(includeFromJson: false, includeToJson: false) +@pragma('vm:prefer-inline') +$CryptoError_IoErrorCopyWith get copyWith => _$CryptoError_IoErrorCopyWithImpl(this, _$identity); + + + +@override +bool operator ==(Object other) { + return identical(this, other) || (other.runtimeType == runtimeType&&other is CryptoError_IoError&&(identical(other.field0, field0) || other.field0 == field0)); +} + + +@override +int get hashCode => Object.hash(runtimeType,field0); + +@override +String toString() { + return 'CryptoError.ioError(field0: $field0)'; +} + + +} + +/// @nodoc +abstract mixin class $CryptoError_IoErrorCopyWith<$Res> implements $CryptoErrorCopyWith<$Res> { + factory $CryptoError_IoErrorCopyWith(CryptoError_IoError value, $Res Function(CryptoError_IoError) _then) = _$CryptoError_IoErrorCopyWithImpl; +@useResult +$Res call({ + String field0 +}); + + + + +} +/// @nodoc +class _$CryptoError_IoErrorCopyWithImpl<$Res> + implements $CryptoError_IoErrorCopyWith<$Res> { + _$CryptoError_IoErrorCopyWithImpl(this._self, this._then); + + final CryptoError_IoError _self; + final $Res Function(CryptoError_IoError) _then; + +/// Create a copy of CryptoError +/// with the given fields replaced by the non-null parameter values. +@pragma('vm:prefer-inline') $Res call({Object? field0 = null,}) { + return _then(CryptoError_IoError( +null == field0 ? _self.field0 : field0 // ignore: cast_nullable_to_non_nullable +as String, + )); +} + + +} + +/// @nodoc + + +class CryptoError_InvalidParameter extends CryptoError { + const CryptoError_InvalidParameter(this.field0): super._(); + + + final String field0; + +/// Create a copy of CryptoError +/// with the given fields replaced by the non-null parameter values. +@JsonKey(includeFromJson: false, includeToJson: false) +@pragma('vm:prefer-inline') +$CryptoError_InvalidParameterCopyWith get copyWith => _$CryptoError_InvalidParameterCopyWithImpl(this, _$identity); + + + +@override +bool operator ==(Object other) { + return identical(this, other) || (other.runtimeType == runtimeType&&other is CryptoError_InvalidParameter&&(identical(other.field0, field0) || other.field0 == field0)); +} + + +@override +int get hashCode => Object.hash(runtimeType,field0); + +@override +String toString() { + return 'CryptoError.invalidParameter(field0: $field0)'; +} + + +} + +/// @nodoc +abstract mixin class $CryptoError_InvalidParameterCopyWith<$Res> implements $CryptoErrorCopyWith<$Res> { + factory $CryptoError_InvalidParameterCopyWith(CryptoError_InvalidParameter value, $Res Function(CryptoError_InvalidParameter) _then) = _$CryptoError_InvalidParameterCopyWithImpl; +@useResult +$Res call({ + String field0 +}); + + + + +} +/// @nodoc +class _$CryptoError_InvalidParameterCopyWithImpl<$Res> + implements $CryptoError_InvalidParameterCopyWith<$Res> { + _$CryptoError_InvalidParameterCopyWithImpl(this._self, this._then); + + final CryptoError_InvalidParameter _self; + final $Res Function(CryptoError_InvalidParameter) _then; + +/// Create a copy of CryptoError +/// with the given fields replaced by the non-null parameter values. +@pragma('vm:prefer-inline') $Res call({Object? field0 = null,}) { + return _then(CryptoError_InvalidParameter( +null == field0 ? _self.field0 : field0 // ignore: cast_nullable_to_non_nullable +as String, + )); +} + + +} + +/// @nodoc + + +class CryptoError_AuthenticationFailed extends CryptoError { + const CryptoError_AuthenticationFailed(): super._(); + + + + + + + +@override +bool operator ==(Object other) { + return identical(this, other) || (other.runtimeType == runtimeType&&other is CryptoError_AuthenticationFailed); +} + + +@override +int get hashCode => runtimeType.hashCode; + +@override +String toString() { + return 'CryptoError.authenticationFailed()'; +} + + +} + + + + +// dart format on diff --git a/linux/CMakeLists.txt b/linux/CMakeLists.txt index 03b0638..d1a9390 100644 --- a/linux/CMakeLists.txt +++ b/linux/CMakeLists.txt @@ -7,88 +7,13 @@ cmake_minimum_required(VERSION 3.10) set(PROJECT_NAME "m_security") project(${PROJECT_NAME} LANGUAGES CXX) -# This value is used when generating builds using this plugin, so it must -# not be changed. -set(PLUGIN_NAME "m_security_plugin") - -# Any new source files that you add to the plugin should be added here. -list(APPEND PLUGIN_SOURCES - "m_security_plugin.cc" -) - -# Define the plugin library target. Its name must not be changed (see comment -# on PLUGIN_NAME above). -add_library(${PLUGIN_NAME} SHARED - ${PLUGIN_SOURCES} -) - -# Apply a standard set of build settings that are configured in the -# application-level CMakeLists.txt. This can be removed for plugins that want -# full control over build settings. -apply_standard_settings(${PLUGIN_NAME}) - -# Symbols are hidden by default to reduce the chance of accidental conflicts -# between plugins. This should not be removed; any symbols that should be -# exported should be explicitly exported with the FLUTTER_PLUGIN_EXPORT macro. -set_target_properties(${PLUGIN_NAME} PROPERTIES - CXX_VISIBILITY_PRESET hidden) -target_compile_definitions(${PLUGIN_NAME} PRIVATE FLUTTER_PLUGIN_IMPL) - -# Source include directories and library dependencies. Add any plugin-specific -# dependencies here. -target_include_directories(${PLUGIN_NAME} INTERFACE - "${CMAKE_CURRENT_SOURCE_DIR}/include") -target_link_libraries(${PLUGIN_NAME} PRIVATE flutter) -target_link_libraries(${PLUGIN_NAME} PRIVATE PkgConfig::GTK) +include("../cargokit/cmake/cargokit.cmake") +apply_cargokit(${PROJECT_NAME} ../rust rust_lib_m_security "") # List of absolute paths to libraries that should be bundled with the plugin. # This list could contain prebuilt libraries, or libraries created by an # external build triggered from this build file. set(m_security_bundled_libraries - "" + "${${PROJECT_NAME}_cargokit_lib}" PARENT_SCOPE ) - -# === Tests === -# These unit tests can be run from a terminal after building the example. - -# Only enable test builds when building the example (which sets this variable) -# so that plugin clients aren't building the tests. -if (${include_${PROJECT_NAME}_tests}) -if(${CMAKE_VERSION} VERSION_LESS "3.11.0") -message("Unit tests require CMake 3.11.0 or later") -else() -set(TEST_RUNNER "${PROJECT_NAME}_test") -enable_testing() - -# Add the Google Test dependency. -include(FetchContent) -FetchContent_Declare( - googletest - URL https://github.com/google/googletest/archive/release-1.11.0.zip -) -# Prevent overriding the parent project's compiler/linker settings -set(gtest_force_shared_crt ON CACHE BOOL "" FORCE) -# Disable install commands for gtest so it doesn't end up in the bundle. -set(INSTALL_GTEST OFF CACHE BOOL "Disable installation of googletest" FORCE) - -FetchContent_MakeAvailable(googletest) - -# The plugin's exported API is not very useful for unit testing, so build the -# sources directly into the test binary rather than using the shared library. -add_executable(${TEST_RUNNER} - test/m_security_plugin_test.cc - ${PLUGIN_SOURCES} -) -apply_standard_settings(${TEST_RUNNER}) -target_include_directories(${TEST_RUNNER} PRIVATE "${CMAKE_CURRENT_SOURCE_DIR}") -target_link_libraries(${TEST_RUNNER} PRIVATE flutter) -target_link_libraries(${TEST_RUNNER} PRIVATE PkgConfig::GTK) -target_link_libraries(${TEST_RUNNER} PRIVATE gtest_main gmock) - -# Enable automatic test discovery. -include(GoogleTest) -gtest_discover_tests(${TEST_RUNNER}) - -endif() # CMake version check -endif() # include_${PROJECT_NAME}_tests \ No newline at end of file diff --git a/linux/include/m_security/m_security_plugin.h b/linux/include/m_security/m_security_plugin.h deleted file mode 100644 index 1011b48..0000000 --- a/linux/include/m_security/m_security_plugin.h +++ /dev/null @@ -1,26 +0,0 @@ -#ifndef FLUTTER_PLUGIN_M_SECURITY_PLUGIN_H_ -#define FLUTTER_PLUGIN_M_SECURITY_PLUGIN_H_ - -#include - -G_BEGIN_DECLS - -#ifdef FLUTTER_PLUGIN_IMPL -#define FLUTTER_PLUGIN_EXPORT __attribute__((visibility("default"))) -#else -#define FLUTTER_PLUGIN_EXPORT -#endif - -typedef struct _MSecurityPlugin MSecurityPlugin; -typedef struct { - GObjectClass parent_class; -} MSecurityPluginClass; - -FLUTTER_PLUGIN_EXPORT GType m_security_plugin_get_type(); - -FLUTTER_PLUGIN_EXPORT void m_security_plugin_register_with_registrar( - FlPluginRegistrar* registrar); - -G_END_DECLS - -#endif // FLUTTER_PLUGIN_M_SECURITY_PLUGIN_H_ diff --git a/linux/m_security_plugin.cc b/linux/m_security_plugin.cc deleted file mode 100644 index ed0ecb1..0000000 --- a/linux/m_security_plugin.cc +++ /dev/null @@ -1,76 +0,0 @@ -#include "include/m_security/m_security_plugin.h" - -#include -#include -#include - -#include - -#include "m_security_plugin_private.h" - -#define M_SECURITY_PLUGIN(obj) \ - (G_TYPE_CHECK_INSTANCE_CAST((obj), m_security_plugin_get_type(), \ - MSecurityPlugin)) - -struct _MSecurityPlugin { - GObject parent_instance; -}; - -G_DEFINE_TYPE(MSecurityPlugin, m_security_plugin, g_object_get_type()) - -// Called when a method call is received from Flutter. -static void m_security_plugin_handle_method_call( - MSecurityPlugin* self, - FlMethodCall* method_call) { - g_autoptr(FlMethodResponse) response = nullptr; - - const gchar* method = fl_method_call_get_name(method_call); - - if (strcmp(method, "getPlatformVersion") == 0) { - response = get_platform_version(); - } else { - response = FL_METHOD_RESPONSE(fl_method_not_implemented_response_new()); - } - - fl_method_call_respond(method_call, response, nullptr); -} - -FlMethodResponse* get_platform_version() { - struct utsname uname_data = {}; - uname(&uname_data); - g_autofree gchar *version = g_strdup_printf("Linux %s", uname_data.version); - g_autoptr(FlValue) result = fl_value_new_string(version); - return FL_METHOD_RESPONSE(fl_method_success_response_new(result)); -} - -static void m_security_plugin_dispose(GObject* object) { - G_OBJECT_CLASS(m_security_plugin_parent_class)->dispose(object); -} - -static void m_security_plugin_class_init(MSecurityPluginClass* klass) { - G_OBJECT_CLASS(klass)->dispose = m_security_plugin_dispose; -} - -static void m_security_plugin_init(MSecurityPlugin* self) {} - -static void method_call_cb(FlMethodChannel* channel, FlMethodCall* method_call, - gpointer user_data) { - MSecurityPlugin* plugin = M_SECURITY_PLUGIN(user_data); - m_security_plugin_handle_method_call(plugin, method_call); -} - -void m_security_plugin_register_with_registrar(FlPluginRegistrar* registrar) { - MSecurityPlugin* plugin = M_SECURITY_PLUGIN( - g_object_new(m_security_plugin_get_type(), nullptr)); - - g_autoptr(FlStandardMethodCodec) codec = fl_standard_method_codec_new(); - g_autoptr(FlMethodChannel) channel = - fl_method_channel_new(fl_plugin_registrar_get_messenger(registrar), - "m_security", - FL_METHOD_CODEC(codec)); - fl_method_channel_set_method_call_handler(channel, method_call_cb, - g_object_ref(plugin), - g_object_unref); - - g_object_unref(plugin); -} diff --git a/linux/m_security_plugin_private.h b/linux/m_security_plugin_private.h deleted file mode 100644 index 022406e..0000000 --- a/linux/m_security_plugin_private.h +++ /dev/null @@ -1,10 +0,0 @@ -#include - -#include "include/m_security/m_security_plugin.h" - -// This file exposes some plugin internals for unit testing. See -// https://github.com/flutter/flutter/issues/88724 for current limitations -// in the unit-testable API. - -// Handles the getPlatformVersion method call. -FlMethodResponse *get_platform_version(); diff --git a/linux/test/m_security_plugin_test.cc b/linux/test/m_security_plugin_test.cc deleted file mode 100644 index 71d4c51..0000000 --- a/linux/test/m_security_plugin_test.cc +++ /dev/null @@ -1,31 +0,0 @@ -#include -#include -#include - -#include "include/m_security/m_security_plugin.h" -#include "m_security_plugin_private.h" - -// This demonstrates a simple unit test of the C portion of this plugin's -// implementation. -// -// Once you have built the plugin's example app, you can run these tests -// from the command line. For instance, for a plugin called my_plugin -// built for x64 debug, run: -// $ build/linux/x64/debug/plugins/my_plugin/my_plugin_test - -namespace m_security { -namespace test { - -TEST(MSecurityPlugin, GetPlatformVersion) { - g_autoptr(FlMethodResponse) response = get_platform_version(); - ASSERT_NE(response, nullptr); - ASSERT_TRUE(FL_IS_METHOD_SUCCESS_RESPONSE(response)); - FlValue* result = fl_method_success_response_get_result( - FL_METHOD_SUCCESS_RESPONSE(response)); - ASSERT_EQ(fl_value_get_type(result), FL_VALUE_TYPE_STRING); - // The full string varies, so just validate that it has the right format. - EXPECT_THAT(fl_value_get_string(result), testing::StartsWith("Linux ")); -} - -} // namespace test -} // namespace m_security diff --git a/macos/Classes/MSecurityPlugin.swift b/macos/Classes/MSecurityPlugin.swift deleted file mode 100644 index 2726576..0000000 --- a/macos/Classes/MSecurityPlugin.swift +++ /dev/null @@ -1,19 +0,0 @@ -import Cocoa -import FlutterMacOS - -public class MSecurityPlugin: NSObject, FlutterPlugin { - public static func register(with registrar: FlutterPluginRegistrar) { - let channel = FlutterMethodChannel(name: "m_security", binaryMessenger: registrar.messenger) - let instance = MSecurityPlugin() - registrar.addMethodCallDelegate(instance, channel: channel) - } - - public func handle(_ call: FlutterMethodCall, result: @escaping FlutterResult) { - switch call.method { - case "getPlatformVersion": - result("macOS " + ProcessInfo.processInfo.operatingSystemVersionString) - default: - result(FlutterMethodNotImplemented) - } - } -} diff --git a/rust_builder/macos/Classes/dummy_file.c b/macos/Classes/dummy_file.c similarity index 100% rename from rust_builder/macos/Classes/dummy_file.c rename to macos/Classes/dummy_file.c diff --git a/macos/m_security.podspec b/macos/m_security.podspec index 99fda25..a69e8ea 100644 --- a/macos/m_security.podspec +++ b/macos/m_security.podspec @@ -5,26 +5,42 @@ Pod::Spec.new do |s| s.name = 'm_security' s.version = '0.0.1' - s.summary = 'A new Flutter plugin project.' + s.summary = 'A high-performance cryptographic SDK for Flutter powered by native Rust via FFI.' s.description = <<-DESC -A new Flutter plugin project. +A high-performance cryptographic SDK for Flutter powered by native Rust via FFI. +Provides authenticated encryption (AES-256-GCM, ChaCha20-Poly1305), modern hashing +(BLAKE3, SHA-3, Argon2id), and key derivation (HKDF-SHA256) with secure memory management. DESC - s.homepage = 'http://example.com' + s.homepage = 'https://github.com/MicroClub-USTHB/M-Security' s.license = { :file => '../LICENSE' } - s.author = { 'Your Company' => 'email@example.com' } + s.author = { 'MicroClub-USTHB' => 'https://github.com/MicroClub-USTHB' } + # This will ensure the source files in Classes/ are included in the native + # builds of apps using this FFI plugin. Podspec does not support relative + # paths, so Classes contains a forwarder C file that relatively imports + # `../src/*` so that the C sources can be shared among all target platforms. s.source = { :path => '.' } - s.source_files = 'Classes/**/*' - - # If your plugin requires a privacy manifest, for example if it collects user - # data, update the PrivacyInfo.xcprivacy file to describe your plugin's - # privacy impact, and then uncomment this line. For more information, - # see https://developer.apple.com/documentation/bundleresources/privacy_manifest_files - # s.resource_bundles = {'m_security_privacy' => ['Resources/PrivacyInfo.xcprivacy']} - + s.source_files = 'Classes/**/*' s.dependency 'FlutterMacOS' s.platform = :osx, '10.11' s.pod_target_xcconfig = { 'DEFINES_MODULE' => 'YES' } s.swift_version = '5.0' + + s.script_phase = { + :name => 'Build Rust library', + # First argument is relative path to the `rust` folder, second is name of rust library + :script => 'sh "$PODS_TARGET_SRCROOT/../cargokit/build_pod.sh" ../rust rust_lib_m_security', + :execution_position => :before_compile, + :input_files => ['${BUILT_PRODUCTS_DIR}/cargokit_phony'], + # Let XCode know that the static library referenced in -force_load below is + # created by this build step. + :output_files => ["${BUILT_PRODUCTS_DIR}/librust_lib_m_security.a"], + } + s.pod_target_xcconfig = { + 'DEFINES_MODULE' => 'YES', + # Flutter.framework does not contain a i386 slice. + 'EXCLUDED_ARCHS[sdk=iphonesimulator*]' => 'i386', + 'OTHER_LDFLAGS' => '-force_load ${BUILT_PRODUCTS_DIR}/librust_lib_m_security.a', + } end diff --git a/pubspec.yaml b/pubspec.yaml index 4d31668..6a4d9c2 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -21,11 +21,9 @@ environment: dependencies: flutter: sdk: flutter - flutter_rust_bridge: 2.11.1 + flutter_rust_bridge: ^2.11.1 freezed_annotation: ^3.1.0 plugin_platform_interface: ^2.0.2 - rust_lib_m_security: - path: rust_builder dev_dependencies: flutter_test: @@ -41,13 +39,12 @@ flutter: plugin: platforms: android: - package: com.example.m_security - pluginClass: MSecurityPlugin + ffiPlugin: true ios: - pluginClass: MSecurityPlugin + ffiPlugin: true linux: - pluginClass: MSecurityPlugin + ffiPlugin: true macos: - pluginClass: MSecurityPlugin + ffiPlugin: true windows: - pluginClass: MSecurityPluginCApi + ffiPlugin: true diff --git a/rust_builder/.gitignore b/rust_builder/.gitignore deleted file mode 100644 index ac5aa98..0000000 --- a/rust_builder/.gitignore +++ /dev/null @@ -1,29 +0,0 @@ -# Miscellaneous -*.class -*.log -*.pyc -*.swp -.DS_Store -.atom/ -.buildlog/ -.history -.svn/ -migrate_working_dir/ - -# IntelliJ related -*.iml -*.ipr -*.iws -.idea/ - -# The .vscode folder contains launch configuration and tasks you configure in -# VS Code which you may wish to be included in version control, so this line -# is commented out by default. -#.vscode/ - -# Flutter/Dart/Pub related -# Libraries should not include pubspec.lock, per https://dart.dev/guides/libraries/private-files#pubspeclock. -/pubspec.lock -**/doc/api/ -.dart_tool/ -build/ diff --git a/rust_builder/README.md b/rust_builder/README.md deleted file mode 100644 index 922615f..0000000 --- a/rust_builder/README.md +++ /dev/null @@ -1 +0,0 @@ -Please ignore this folder, which is just glue to build Rust with Flutter. \ No newline at end of file diff --git a/rust_builder/android/.gitignore b/rust_builder/android/.gitignore deleted file mode 100644 index 161bdcd..0000000 --- a/rust_builder/android/.gitignore +++ /dev/null @@ -1,9 +0,0 @@ -*.iml -.gradle -/local.properties -/.idea/workspace.xml -/.idea/libraries -.DS_Store -/build -/captures -.cxx diff --git a/rust_builder/android/build.gradle b/rust_builder/android/build.gradle deleted file mode 100644 index 0ec140d..0000000 --- a/rust_builder/android/build.gradle +++ /dev/null @@ -1,56 +0,0 @@ -// The Android Gradle Plugin builds the native code with the Android NDK. - -group 'com.flutter_rust_bridge.rust_lib_m_security' -version '1.0' - -buildscript { - repositories { - google() - mavenCentral() - } - - dependencies { - // The Android Gradle Plugin knows how to build native code with the NDK. - classpath 'com.android.tools.build:gradle:7.3.0' - } -} - -rootProject.allprojects { - repositories { - google() - mavenCentral() - } -} - -apply plugin: 'com.android.library' - -android { - if (project.android.hasProperty("namespace")) { - namespace 'com.flutter_rust_bridge.rust_lib_m_security' - } - - // Bumping the plugin compileSdkVersion requires all clients of this plugin - // to bump the version in their app. - compileSdkVersion 33 - - // Use the NDK version - // declared in /android/app/build.gradle file of the Flutter project. - // Replace it with a version number if this plugin requires a specfic NDK version. - // (e.g. ndkVersion "23.1.7779620") - ndkVersion android.ndkVersion - - compileOptions { - sourceCompatibility JavaVersion.VERSION_1_8 - targetCompatibility JavaVersion.VERSION_1_8 - } - - defaultConfig { - minSdkVersion 19 - } -} - -apply from: "../cargokit/gradle/plugin.gradle" -cargokit { - manifestDir = "../../rust" - libname = "rust_lib_m_security" -} diff --git a/rust_builder/android/settings.gradle b/rust_builder/android/settings.gradle deleted file mode 100644 index 065bc09..0000000 --- a/rust_builder/android/settings.gradle +++ /dev/null @@ -1 +0,0 @@ -rootProject.name = 'rust_lib_m_security' diff --git a/rust_builder/android/src/main/AndroidManifest.xml b/rust_builder/android/src/main/AndroidManifest.xml deleted file mode 100644 index 40d5f19..0000000 --- a/rust_builder/android/src/main/AndroidManifest.xml +++ /dev/null @@ -1,3 +0,0 @@ - - diff --git a/rust_builder/ios/rust_lib_m_security.podspec b/rust_builder/ios/rust_lib_m_security.podspec deleted file mode 100644 index fcd891f..0000000 --- a/rust_builder/ios/rust_lib_m_security.podspec +++ /dev/null @@ -1,45 +0,0 @@ -# -# To learn more about a Podspec see http://guides.cocoapods.org/syntax/podspec.html. -# Run `pod lib lint rust_lib_m_security.podspec` to validate before publishing. -# -Pod::Spec.new do |s| - s.name = 'rust_lib_m_security' - s.version = '0.0.1' - s.summary = 'A new Flutter FFI plugin project.' - s.description = <<-DESC -A new Flutter FFI plugin project. - DESC - s.homepage = 'http://example.com' - s.license = { :file => '../LICENSE' } - s.author = { 'Your Company' => 'email@example.com' } - - # This will ensure the source files in Classes/ are included in the native - # builds of apps using this FFI plugin. Podspec does not support relative - # paths, so Classes contains a forwarder C file that relatively imports - # `../src/*` so that the C sources can be shared among all target platforms. - s.source = { :path => '.' } - s.source_files = 'Classes/**/*' - s.dependency 'Flutter' - s.platform = :ios, '11.0' - - # Flutter.framework does not contain a i386 slice. - s.pod_target_xcconfig = { 'DEFINES_MODULE' => 'YES', 'EXCLUDED_ARCHS[sdk=iphonesimulator*]' => 'i386' } - s.swift_version = '5.0' - - s.script_phase = { - :name => 'Build Rust library', - # First argument is relative path to the `rust` folder, second is name of rust library - :script => 'sh "$PODS_TARGET_SRCROOT/../cargokit/build_pod.sh" ../../rust rust_lib_m_security', - :execution_position => :before_compile, - :input_files => ['${BUILT_PRODUCTS_DIR}/cargokit_phony'], - # Let XCode know that the static library referenced in -force_load below is - # created by this build step. - :output_files => ["${BUILT_PRODUCTS_DIR}/librust_lib_m_security.a"], - } - s.pod_target_xcconfig = { - 'DEFINES_MODULE' => 'YES', - # Flutter.framework does not contain a i386 slice. - 'EXCLUDED_ARCHS[sdk=iphonesimulator*]' => 'i386', - 'OTHER_LDFLAGS' => '-force_load ${BUILT_PRODUCTS_DIR}/librust_lib_m_security.a', - } -end \ No newline at end of file diff --git a/rust_builder/linux/CMakeLists.txt b/rust_builder/linux/CMakeLists.txt deleted file mode 100644 index c2c4423..0000000 --- a/rust_builder/linux/CMakeLists.txt +++ /dev/null @@ -1,19 +0,0 @@ -# The Flutter tooling requires that developers have CMake 3.10 or later -# installed. You should not increase this version, as doing so will cause -# the plugin to fail to compile for some customers of the plugin. -cmake_minimum_required(VERSION 3.10) - -# Project-level configuration. -set(PROJECT_NAME "rust_lib_m_security") -project(${PROJECT_NAME} LANGUAGES CXX) - -include("../cargokit/cmake/cargokit.cmake") -apply_cargokit(${PROJECT_NAME} ../../rust rust_lib_m_security "") - -# List of absolute paths to libraries that should be bundled with the plugin. -# This list could contain prebuilt libraries, or libraries created by an -# external build triggered from this build file. -set(rust_lib_m_security_bundled_libraries - "${${PROJECT_NAME}_cargokit_lib}" - PARENT_SCOPE -) diff --git a/rust_builder/macos/rust_lib_m_security.podspec b/rust_builder/macos/rust_lib_m_security.podspec deleted file mode 100644 index 5f86741..0000000 --- a/rust_builder/macos/rust_lib_m_security.podspec +++ /dev/null @@ -1,44 +0,0 @@ -# -# To learn more about a Podspec see http://guides.cocoapods.org/syntax/podspec.html. -# Run `pod lib lint rust_lib_m_security.podspec` to validate before publishing. -# -Pod::Spec.new do |s| - s.name = 'rust_lib_m_security' - s.version = '0.0.1' - s.summary = 'A new Flutter FFI plugin project.' - s.description = <<-DESC -A new Flutter FFI plugin project. - DESC - s.homepage = 'http://example.com' - s.license = { :file => '../LICENSE' } - s.author = { 'Your Company' => 'email@example.com' } - - # This will ensure the source files in Classes/ are included in the native - # builds of apps using this FFI plugin. Podspec does not support relative - # paths, so Classes contains a forwarder C file that relatively imports - # `../src/*` so that the C sources can be shared among all target platforms. - s.source = { :path => '.' } - s.source_files = 'Classes/**/*' - s.dependency 'FlutterMacOS' - - s.platform = :osx, '10.11' - s.pod_target_xcconfig = { 'DEFINES_MODULE' => 'YES' } - s.swift_version = '5.0' - - s.script_phase = { - :name => 'Build Rust library', - # First argument is relative path to the `rust` folder, second is name of rust library - :script => 'sh "$PODS_TARGET_SRCROOT/../cargokit/build_pod.sh" ../../rust rust_lib_m_security', - :execution_position => :before_compile, - :input_files => ['${BUILT_PRODUCTS_DIR}/cargokit_phony'], - # Let XCode know that the static library referenced in -force_load below is - # created by this build step. - :output_files => ["${BUILT_PRODUCTS_DIR}/librust_lib_m_security.a"], - } - s.pod_target_xcconfig = { - 'DEFINES_MODULE' => 'YES', - # Flutter.framework does not contain a i386 slice. - 'EXCLUDED_ARCHS[sdk=iphonesimulator*]' => 'i386', - 'OTHER_LDFLAGS' => '-force_load ${BUILT_PRODUCTS_DIR}/librust_lib_m_security.a', - } -end \ No newline at end of file diff --git a/rust_builder/pubspec.yaml b/rust_builder/pubspec.yaml deleted file mode 100644 index 0ef7a50..0000000 --- a/rust_builder/pubspec.yaml +++ /dev/null @@ -1,34 +0,0 @@ -name: rust_lib_m_security -description: "Utility to build Rust code" -version: 0.0.1 -publish_to: none - -environment: - sdk: '>=3.3.0 <4.0.0' - flutter: '>=3.3.0' - -dependencies: - flutter: - sdk: flutter - plugin_platform_interface: ^2.0.2 - -dev_dependencies: - ffi: ^2.0.2 - ffigen: ^11.0.0 - flutter_test: - sdk: flutter - flutter_lints: ^2.0.0 - -flutter: - plugin: - platforms: - android: - ffiPlugin: true - ios: - ffiPlugin: true - linux: - ffiPlugin: true - macos: - ffiPlugin: true - windows: - ffiPlugin: true diff --git a/rust_builder/windows/.gitignore b/rust_builder/windows/.gitignore deleted file mode 100644 index b3eb2be..0000000 --- a/rust_builder/windows/.gitignore +++ /dev/null @@ -1,17 +0,0 @@ -flutter/ - -# Visual Studio user-specific files. -*.suo -*.user -*.userosscache -*.sln.docstates - -# Visual Studio build-related files. -x64/ -x86/ - -# Visual Studio cache files -# files ending in .cache can be ignored -*.[Cc]ache -# but keep track of directories ending in .cache -!*.[Cc]ache/ diff --git a/rust_builder/windows/CMakeLists.txt b/rust_builder/windows/CMakeLists.txt deleted file mode 100644 index 8430dfe..0000000 --- a/rust_builder/windows/CMakeLists.txt +++ /dev/null @@ -1,20 +0,0 @@ -# The Flutter tooling requires that developers have a version of Visual Studio -# installed that includes CMake 3.14 or later. You should not increase this -# version, as doing so will cause the plugin to fail to compile for some -# customers of the plugin. -cmake_minimum_required(VERSION 3.14) - -# Project-level configuration. -set(PROJECT_NAME "rust_lib_m_security") -project(${PROJECT_NAME} LANGUAGES CXX) - -include("../cargokit/cmake/cargokit.cmake") -apply_cargokit(${PROJECT_NAME} ../../../../../../rust rust_lib_m_security "") - -# List of absolute paths to libraries that should be bundled with the plugin. -# This list could contain prebuilt libraries, or libraries created by an -# external build triggered from this build file. -set(rust_lib_m_security_bundled_libraries - "${${PROJECT_NAME}_cargokit_lib}" - PARENT_SCOPE -) diff --git a/windows/CMakeLists.txt b/windows/CMakeLists.txt index af222c6..dd5bafb 100644 --- a/windows/CMakeLists.txt +++ b/windows/CMakeLists.txt @@ -8,93 +8,13 @@ cmake_minimum_required(VERSION 3.14) set(PROJECT_NAME "m_security") project(${PROJECT_NAME} LANGUAGES CXX) -# Explicitly opt in to modern CMake behaviors to avoid warnings with recent -# versions of CMake. -cmake_policy(VERSION 3.14...3.25) - -# This value is used when generating builds using this plugin, so it must -# not be changed -set(PLUGIN_NAME "m_security_plugin") - -# Any new source files that you add to the plugin should be added here. -list(APPEND PLUGIN_SOURCES - "m_security_plugin.cpp" - "m_security_plugin.h" -) - -# Define the plugin library target. Its name must not be changed (see comment -# on PLUGIN_NAME above). -add_library(${PLUGIN_NAME} SHARED - "include/m_security/m_security_plugin_c_api.h" - "m_security_plugin_c_api.cpp" - ${PLUGIN_SOURCES} -) - -# Apply a standard set of build settings that are configured in the -# application-level CMakeLists.txt. This can be removed for plugins that want -# full control over build settings. -apply_standard_settings(${PLUGIN_NAME}) - -# Symbols are hidden by default to reduce the chance of accidental conflicts -# between plugins. This should not be removed; any symbols that should be -# exported should be explicitly exported with the FLUTTER_PLUGIN_EXPORT macro. -set_target_properties(${PLUGIN_NAME} PROPERTIES - CXX_VISIBILITY_PRESET hidden) -target_compile_definitions(${PLUGIN_NAME} PRIVATE FLUTTER_PLUGIN_IMPL) - -# Source include directories and library dependencies. Add any plugin-specific -# dependencies here. -target_include_directories(${PLUGIN_NAME} INTERFACE - "${CMAKE_CURRENT_SOURCE_DIR}/include") -target_link_libraries(${PLUGIN_NAME} PRIVATE flutter flutter_wrapper_plugin) +include("../cargokit/cmake/cargokit.cmake") +apply_cargokit(${PROJECT_NAME} ../rust rust_lib_m_security "") # List of absolute paths to libraries that should be bundled with the plugin. # This list could contain prebuilt libraries, or libraries created by an # external build triggered from this build file. set(m_security_bundled_libraries - "" + "${${PROJECT_NAME}_cargokit_lib}" PARENT_SCOPE ) - -# === Tests === -# These unit tests can be run from a terminal after building the example, or -# from Visual Studio after opening the generated solution file. - -# Only enable test builds when building the example (which sets this variable) -# so that plugin clients aren't building the tests. -if (${include_${PROJECT_NAME}_tests}) -set(TEST_RUNNER "${PROJECT_NAME}_test") -enable_testing() - -# Add the Google Test dependency. -include(FetchContent) -FetchContent_Declare( - googletest - URL https://github.com/google/googletest/archive/release-1.11.0.zip -) -# Prevent overriding the parent project's compiler/linker settings -set(gtest_force_shared_crt ON CACHE BOOL "" FORCE) -# Disable install commands for gtest so it doesn't end up in the bundle. -set(INSTALL_GTEST OFF CACHE BOOL "Disable installation of googletest" FORCE) -FetchContent_MakeAvailable(googletest) - -# The plugin's C API is not very useful for unit testing, so build the sources -# directly into the test binary rather than using the DLL. -add_executable(${TEST_RUNNER} - test/m_security_plugin_test.cpp - ${PLUGIN_SOURCES} -) -apply_standard_settings(${TEST_RUNNER}) -target_include_directories(${TEST_RUNNER} PRIVATE "${CMAKE_CURRENT_SOURCE_DIR}") -target_link_libraries(${TEST_RUNNER} PRIVATE flutter_wrapper_plugin) -target_link_libraries(${TEST_RUNNER} PRIVATE gtest_main gmock) -# flutter_wrapper_plugin has link dependencies on the Flutter DLL. -add_custom_command(TARGET ${TEST_RUNNER} POST_BUILD - COMMAND ${CMAKE_COMMAND} -E copy_if_different - "${FLUTTER_LIBRARY}" $ -) - -# Enable automatic test discovery. -include(GoogleTest) -gtest_discover_tests(${TEST_RUNNER}) -endif() diff --git a/windows/include/m_security/m_security_plugin_c_api.h b/windows/include/m_security/m_security_plugin_c_api.h deleted file mode 100644 index 5362c3d..0000000 --- a/windows/include/m_security/m_security_plugin_c_api.h +++ /dev/null @@ -1,23 +0,0 @@ -#ifndef FLUTTER_PLUGIN_M_SECURITY_PLUGIN_C_API_H_ -#define FLUTTER_PLUGIN_M_SECURITY_PLUGIN_C_API_H_ - -#include - -#ifdef FLUTTER_PLUGIN_IMPL -#define FLUTTER_PLUGIN_EXPORT __declspec(dllexport) -#else -#define FLUTTER_PLUGIN_EXPORT __declspec(dllimport) -#endif - -#if defined(__cplusplus) -extern "C" { -#endif - -FLUTTER_PLUGIN_EXPORT void MSecurityPluginCApiRegisterWithRegistrar( - FlutterDesktopPluginRegistrarRef registrar); - -#if defined(__cplusplus) -} // extern "C" -#endif - -#endif // FLUTTER_PLUGIN_M_SECURITY_PLUGIN_C_API_H_ diff --git a/windows/m_security_plugin.cpp b/windows/m_security_plugin.cpp deleted file mode 100644 index 092164a..0000000 --- a/windows/m_security_plugin.cpp +++ /dev/null @@ -1,59 +0,0 @@ -#include "m_security_plugin.h" - -// This must be included before many other Windows headers. -#include - -// For getPlatformVersion; remove unless needed for your plugin implementation. -#include - -#include -#include -#include - -#include -#include - -namespace m_security { - -// static -void MSecurityPlugin::RegisterWithRegistrar( - flutter::PluginRegistrarWindows *registrar) { - auto channel = - std::make_unique>( - registrar->messenger(), "m_security", - &flutter::StandardMethodCodec::GetInstance()); - - auto plugin = std::make_unique(); - - channel->SetMethodCallHandler( - [plugin_pointer = plugin.get()](const auto &call, auto result) { - plugin_pointer->HandleMethodCall(call, std::move(result)); - }); - - registrar->AddPlugin(std::move(plugin)); -} - -MSecurityPlugin::MSecurityPlugin() {} - -MSecurityPlugin::~MSecurityPlugin() {} - -void MSecurityPlugin::HandleMethodCall( - const flutter::MethodCall &method_call, - std::unique_ptr> result) { - if (method_call.method_name().compare("getPlatformVersion") == 0) { - std::ostringstream version_stream; - version_stream << "Windows "; - if (IsWindows10OrGreater()) { - version_stream << "10+"; - } else if (IsWindows8OrGreater()) { - version_stream << "8"; - } else if (IsWindows7OrGreater()) { - version_stream << "7"; - } - result->Success(flutter::EncodableValue(version_stream.str())); - } else { - result->NotImplemented(); - } -} - -} // namespace m_security diff --git a/windows/m_security_plugin.h b/windows/m_security_plugin.h deleted file mode 100644 index d3769b9..0000000 --- a/windows/m_security_plugin.h +++ /dev/null @@ -1,31 +0,0 @@ -#ifndef FLUTTER_PLUGIN_M_SECURITY_PLUGIN_H_ -#define FLUTTER_PLUGIN_M_SECURITY_PLUGIN_H_ - -#include -#include - -#include - -namespace m_security { - -class MSecurityPlugin : public flutter::Plugin { - public: - static void RegisterWithRegistrar(flutter::PluginRegistrarWindows *registrar); - - MSecurityPlugin(); - - virtual ~MSecurityPlugin(); - - // Disallow copy and assign. - MSecurityPlugin(const MSecurityPlugin&) = delete; - MSecurityPlugin& operator=(const MSecurityPlugin&) = delete; - - // Called when a method is called on this plugin's channel from Dart. - void HandleMethodCall( - const flutter::MethodCall &method_call, - std::unique_ptr> result); -}; - -} // namespace m_security - -#endif // FLUTTER_PLUGIN_M_SECURITY_PLUGIN_H_ diff --git a/windows/m_security_plugin_c_api.cpp b/windows/m_security_plugin_c_api.cpp deleted file mode 100644 index b7e2244..0000000 --- a/windows/m_security_plugin_c_api.cpp +++ /dev/null @@ -1,12 +0,0 @@ -#include "include/m_security/m_security_plugin_c_api.h" - -#include - -#include "m_security_plugin.h" - -void MSecurityPluginCApiRegisterWithRegistrar( - FlutterDesktopPluginRegistrarRef registrar) { - m_security::MSecurityPlugin::RegisterWithRegistrar( - flutter::PluginRegistrarManager::GetInstance() - ->GetRegistrar(registrar)); -} diff --git a/windows/test/m_security_plugin_test.cpp b/windows/test/m_security_plugin_test.cpp deleted file mode 100644 index d5fc23e..0000000 --- a/windows/test/m_security_plugin_test.cpp +++ /dev/null @@ -1,43 +0,0 @@ -#include -#include -#include -#include -#include - -#include -#include -#include - -#include "m_security_plugin.h" - -namespace m_security { -namespace test { - -namespace { - -using flutter::EncodableMap; -using flutter::EncodableValue; -using flutter::MethodCall; -using flutter::MethodResultFunctions; - -} // namespace - -TEST(MSecurityPlugin, GetPlatformVersion) { - MSecurityPlugin plugin; - // Save the reply value from the success callback. - std::string result_string; - plugin.HandleMethodCall( - MethodCall("getPlatformVersion", std::make_unique()), - std::make_unique>( - [&result_string](const EncodableValue* result) { - result_string = std::get(*result); - }, - nullptr, nullptr)); - - // Since the exact string varies by host, just ensure that it's a string - // with the expected format. - EXPECT_TRUE(result_string.rfind("Windows ", 0) == 0); -} - -} // namespace test -} // namespace m_security From 7185ea06338e553e961e4ff7ad5de857b5e58443 Mon Sep 17 00:00:00 2001 From: Adel HB Date: Fri, 6 Mar 2026 14:59:43 +0100 Subject: [PATCH 3/6] Made sure everything is consistant and ready to publish --- RELEASE_GUIDE.md | 18 ++++++++++++++++-- rust/Cargo.lock | 2 +- rust/Cargo.toml | 2 +- 3 files changed, 18 insertions(+), 4 deletions(-) diff --git a/RELEASE_GUIDE.md b/RELEASE_GUIDE.md index 356df6c..d20fc00 100644 --- a/RELEASE_GUIDE.md +++ b/RELEASE_GUIDE.md @@ -29,7 +29,7 @@ git checkout -b release/vX.Y.Z ### 2. Update Version Numbers -Update the version in these files: +Update the version in **all** of these files: **`pubspec.yaml`** (root): ```yaml @@ -42,6 +42,16 @@ version: X.Y.Z version = "X.Y.Z" ``` +**`ios/m_security.podspec`**: +```ruby +s.version = 'X.Y.Z' +``` + +**`macos/m_security.podspec`**: +```ruby +s.version = 'X.Y.Z' +``` + ### 3. Update CHANGELOG.md Move the `## Unreleased` section content under a new version header with the current date: @@ -120,7 +130,7 @@ Using the GitHub CLI: ```bash gh release create vX.Y.Z \ --title "vX.Y.Z" \ - --notes-file CHANGELOG_EXCERPT.md + --generate-notes ``` Or via the GitHub web UI: @@ -204,13 +214,17 @@ Use this checklist when preparing a release: - [ ] Version updated in `pubspec.yaml` - [ ] Version updated in `rust/Cargo.toml` +- [ ] Version updated in `ios/m_security.podspec` +- [ ] Version updated in `macos/m_security.podspec` - [ ] CHANGELOG.md updated with release date - [ ] All Rust tests pass (`cargo test`) - [ ] Clippy clean (`cargo clippy -- -D warnings`) +- [ ] FRB codegen runs cleanly (`flutter_rust_bridge_codegen generate`) - [ ] Dart analysis clean (`dart analyze`) - [ ] Integration tests pass - [ ] CI pipeline passes on the PR - [ ] PR merged to `main` +- [ ] Dry-run publish passes (`dart pub publish --dry-run`) - [ ] Git tag created and pushed - [ ] GitHub Release created - [ ] Published to pub.dev (`dart pub publish`) diff --git a/rust/Cargo.lock b/rust/Cargo.lock index 8558b91..da0f06e 100644 --- a/rust/Cargo.lock +++ b/rust/Cargo.lock @@ -893,7 +893,7 @@ checksum = "c08c74e62047bb2de4ff487b251e4a92e24f48745648451635cec7d591162d9f" [[package]] name = "rust_lib_m_security" -version = "0.1.0" +version = "0.0.1" dependencies = [ "aes-gcm", "argon2", diff --git a/rust/Cargo.toml b/rust/Cargo.toml index ee9f2ab..073dc92 100644 --- a/rust/Cargo.toml +++ b/rust/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "rust_lib_m_security" -version = "0.1.0" +version = "0.0.1" edition = "2021" [lib] From 01a6e811d10b23805621ab10321f46474089aeb4 Mon Sep 17 00:00:00 2001 From: Adel HB Date: Fri, 6 Mar 2026 15:17:50 +0100 Subject: [PATCH 4/6] Changed rust lib name to fit the packaage name "m_security" --- android/build.gradle | 2 +- ios/m_security.podspec | 6 +- lib/src/rust/frb_generated.dart | 2 +- linux/CMakeLists.txt | 2 +- macos/m_security.podspec | 6 +- rust/Cargo.lock | 296 +++++++++++++++----------------- rust/Cargo.toml | 2 +- windows/CMakeLists.txt | 2 +- 8 files changed, 150 insertions(+), 168 deletions(-) diff --git a/android/build.gradle b/android/build.gradle index 8e49ee0..5aa41a0 100644 --- a/android/build.gradle +++ b/android/build.gradle @@ -52,5 +52,5 @@ android { apply from: "../cargokit/gradle/plugin.gradle" cargokit { manifestDir = "../rust" - libname = "rust_lib_m_security" + libname = "m_security" } diff --git a/ios/m_security.podspec b/ios/m_security.podspec index 21cd413..5fc1365 100644 --- a/ios/m_security.podspec +++ b/ios/m_security.podspec @@ -31,17 +31,17 @@ Provides authenticated encryption (AES-256-GCM, ChaCha20-Poly1305), modern hashi s.script_phase = { :name => 'Build Rust library', # First argument is relative path to the `rust` folder, second is name of rust library - :script => 'sh "$PODS_TARGET_SRCROOT/../cargokit/build_pod.sh" ../rust rust_lib_m_security', + :script => 'sh "$PODS_TARGET_SRCROOT/../cargokit/build_pod.sh" ../rust m_security', :execution_position => :before_compile, :input_files => ['${BUILT_PRODUCTS_DIR}/cargokit_phony'], # Let XCode know that the static library referenced in -force_load below is # created by this build step. - :output_files => ["${BUILT_PRODUCTS_DIR}/librust_lib_m_security.a"], + :output_files => ["${BUILT_PRODUCTS_DIR}/libm_security.a"], } s.pod_target_xcconfig = { 'DEFINES_MODULE' => 'YES', # Flutter.framework does not contain a i386 slice. 'EXCLUDED_ARCHS[sdk=iphonesimulator*]' => 'i386', - 'OTHER_LDFLAGS' => '-force_load ${BUILT_PRODUCTS_DIR}/librust_lib_m_security.a', + 'OTHER_LDFLAGS' => '-force_load ${BUILT_PRODUCTS_DIR}/libm_security.a', } end diff --git a/lib/src/rust/frb_generated.dart b/lib/src/rust/frb_generated.dart index a3972ab..72e4e4f 100644 --- a/lib/src/rust/frb_generated.dart +++ b/lib/src/rust/frb_generated.dart @@ -75,7 +75,7 @@ class RustLib extends BaseEntrypoint { static const kDefaultExternalLibraryLoaderConfig = ExternalLibraryLoaderConfig( - stem: 'rust_lib_m_security', + stem: 'm_security', ioDirectory: 'rust/target/release/', webPrefix: 'pkg/', ); diff --git a/linux/CMakeLists.txt b/linux/CMakeLists.txt index d1a9390..24bd340 100644 --- a/linux/CMakeLists.txt +++ b/linux/CMakeLists.txt @@ -8,7 +8,7 @@ set(PROJECT_NAME "m_security") project(${PROJECT_NAME} LANGUAGES CXX) include("../cargokit/cmake/cargokit.cmake") -apply_cargokit(${PROJECT_NAME} ../rust rust_lib_m_security "") +apply_cargokit(${PROJECT_NAME} ../rust m_security "") # List of absolute paths to libraries that should be bundled with the plugin. # This list could contain prebuilt libraries, or libraries created by an diff --git a/macos/m_security.podspec b/macos/m_security.podspec index a69e8ea..22b1345 100644 --- a/macos/m_security.podspec +++ b/macos/m_security.podspec @@ -30,17 +30,17 @@ Provides authenticated encryption (AES-256-GCM, ChaCha20-Poly1305), modern hashi s.script_phase = { :name => 'Build Rust library', # First argument is relative path to the `rust` folder, second is name of rust library - :script => 'sh "$PODS_TARGET_SRCROOT/../cargokit/build_pod.sh" ../rust rust_lib_m_security', + :script => 'sh "$PODS_TARGET_SRCROOT/../cargokit/build_pod.sh" ../rust m_security', :execution_position => :before_compile, :input_files => ['${BUILT_PRODUCTS_DIR}/cargokit_phony'], # Let XCode know that the static library referenced in -force_load below is # created by this build step. - :output_files => ["${BUILT_PRODUCTS_DIR}/librust_lib_m_security.a"], + :output_files => ["${BUILT_PRODUCTS_DIR}/libm_security.a"], } s.pod_target_xcconfig = { 'DEFINES_MODULE' => 'YES', # Flutter.framework does not contain a i386 slice. 'EXCLUDED_ARCHS[sdk=iphonesimulator*]' => 'i386', - 'OTHER_LDFLAGS' => '-force_load ${BUILT_PRODUCTS_DIR}/librust_lib_m_security.a', + 'OTHER_LDFLAGS' => '-force_load ${BUILT_PRODUCTS_DIR}/libm_security.a', } end diff --git a/rust/Cargo.lock b/rust/Cargo.lock index da0f06e..b66e884 100644 --- a/rust/Cargo.lock +++ b/rust/Cargo.lock @@ -4,18 +4,18 @@ version = 4 [[package]] name = "addr2line" -version = "0.21.0" +version = "0.25.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8a30b2e23b9e17a9f90641c7ab1549cd9b44f296d3ccbf309d2863cfe398a0cb" +checksum = "1b5d307320b3181d6d7954e663bd7c774a838b8220fe0593c86d9fb09f498b4b" dependencies = [ "gimli", ] [[package]] -name = "adler" -version = "1.0.2" +name = "adler2" +version = "2.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f26201604c87b1e01bd3d98f8d5d9a8fcbb815e8cedb41ffccbeb4bf593a35fe" +checksum = "320119579fcad9c21884f5c4861d16174d0e06250625266f50fe6898340abefa" [[package]] name = "aead" @@ -54,9 +54,9 @@ dependencies = [ [[package]] name = "aho-corasick" -version = "1.1.2" +version = "1.1.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b2969dcb958b36655471fc61f7e416fa76033bdd4bfed0678d8fee1e2d07a1f0" +checksum = "ddd31a130427c27518df266943a5308ed92d4b226cc639f5a8f1002816174301" dependencies = [ "memchr", ] @@ -91,9 +91,9 @@ dependencies = [ [[package]] name = "anyhow" -version = "1.0.75" +version = "1.0.102" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a4668cab20f66d8d020e1fbc0ebe47217433c1b6c8f2040faf858554e394ace6" +checksum = "7f202df86484c868dbad7eaa557ef785d5c66295e41b460ef922eca0723b842c" [[package]] name = "argon2" @@ -125,25 +125,19 @@ version = "0.5.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c59bdb34bc650a32731b31bd8f0829cc15d24a708ee31559e0bb34f2bc320cba" -[[package]] -name = "autocfg" -version = "1.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa" - [[package]] name = "backtrace" -version = "0.3.69" +version = "0.3.76" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2089b7e3f35b9dd2d0ed921ead4f6d318c27680d4a5bd167b3ee120edb105837" +checksum = "bb531853791a215d7c62a30daf0dde835f381ab5de4589cfe7c649d2cbe92bd6" dependencies = [ "addr2line", - "cc", "cfg-if", "libc", "miniz_oxide", "object", "rustc-demangle", + "windows-link", ] [[package]] @@ -154,9 +148,9 @@ checksum = "2af50177e190e07a26ab74f8b1efbfe2ef87da2116221318cb1c2e82baf7de06" [[package]] name = "bitflags" -version = "2.10.0" +version = "2.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "812e12b5285cc515a9c72a5c1d3b6d46a19dac5acfef5265968c166106e31dd3" +checksum = "843867be96c8daad0d758b57df9392b6d8d271134fce549de6ce169ff98a92af" [[package]] name = "blake2" @@ -198,15 +192,15 @@ checksum = "832133bbabbbaa9fbdba793456a2827627a7d2b8fb96032fa1e7666d7895832b" [[package]] name = "bumpalo" -version = "3.14.0" +version = "3.20.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7f30e7476521f6f8af1a1c4c0b8cc94f0bee37d91763d0ca2665f299b6cd8aec" +checksum = "5d20789868f4b01b2f2caec9f5c4e0213b41e3e5702a50157d699ae31ced2fcb" [[package]] name = "bytemuck" -version = "1.14.0" +version = "1.25.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "374d28ec25809ee0e23827c2ab573d729e293f281dfe393500e7ad618baa61c6" +checksum = "c8efb64bd706a16a1bdde310ae86b351e4d21550d98d056f22f8a7f7a2183fec" [[package]] name = "byteorder" @@ -216,9 +210,9 @@ checksum = "1fd0f2584146f6f2ef48085050886acf353beff7305ebd1ae69500e27c67f64b" [[package]] name = "cc" -version = "1.2.55" +version = "1.2.56" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "47b26a0954ae34af09b50f0de26458fa95369a0d478d8236d3f93082b219bd29" +checksum = "aebf35691d1bfb0ac386a69bac2fde4dd276fb618cf8bf4f5318fe285e821bb2" dependencies = [ "find-msvc-tools", "jobserver", @@ -228,9 +222,9 @@ dependencies = [ [[package]] name = "cfg-if" -version = "1.0.0" +version = "1.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" +checksum = "9330f8b2ff13f34540b44e946ef35111825727b38d33286ef986142615121801" [[package]] name = "chacha20" @@ -294,9 +288,9 @@ dependencies = [ [[package]] name = "crypto-common" -version = "0.1.6" +version = "0.1.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1bfb12502f3fc46cca1bb51ac28df9d618d813cdc3d2f25b9fe775a34af26bb3" +checksum = "78c8292055d1c1df0cce5d180393dc8cce0abec0a7102adb6c7b1eef6016d60a" dependencies = [ "generic-array", "rand_core", @@ -416,9 +410,9 @@ dependencies = [ [[package]] name = "futures" -version = "0.3.31" +version = "0.3.32" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "65bc07b1a8bc7c85c5f2e110c476c7389b4554ba72af57d8445ea63a576b0876" +checksum = "8b147ee9d1f6d097cef9ce628cd2ee62288d963e16fb287bd9286455b241382d" dependencies = [ "futures-channel", "futures-core", @@ -431,9 +425,9 @@ dependencies = [ [[package]] name = "futures-channel" -version = "0.3.31" +version = "0.3.32" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2dff15bf788c671c1934e366d07e30c1814a8ef514e1af724a602e8a2fbe1b10" +checksum = "07bbe89c50d7a535e539b8c17bc0b49bdb77747034daa8087407d655f3f7cc1d" dependencies = [ "futures-core", "futures-sink", @@ -441,15 +435,15 @@ dependencies = [ [[package]] name = "futures-core" -version = "0.3.31" +version = "0.3.32" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "05f29059c0c2090612e8d742178b0580d2dc940c837851ad723096f87af6663e" +checksum = "7e3450815272ef58cec6d564423f6e755e25379b217b0bc688e295ba24df6b1d" [[package]] name = "futures-executor" -version = "0.3.31" +version = "0.3.32" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1e28d1d997f585e54aebc3f97d39e72338912123a67330d723fdbb564d646c9f" +checksum = "baf29c38818342a3b26b5b923639e7b1f4a61fc5e76102d4b1981c6dc7a7579d" dependencies = [ "futures-core", "futures-task", @@ -458,15 +452,15 @@ dependencies = [ [[package]] name = "futures-io" -version = "0.3.31" +version = "0.3.32" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9e5c1b78ca4aae1ac06c48a526a655760685149f0d465d21f37abfe57ce075c6" +checksum = "cecba35d7ad927e23624b22ad55235f2239cfa44fd10428eecbeba6d6a717718" [[package]] name = "futures-macro" -version = "0.3.31" +version = "0.3.32" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "162ee34ebcb7c64a8abebc059ce0fee27c2262618d7b60ed8faf72fef13c3650" +checksum = "e835b70203e41293343137df5c0664546da5745f82ec9b84d40be8336958447b" dependencies = [ "proc-macro2", "quote", @@ -475,21 +469,21 @@ dependencies = [ [[package]] name = "futures-sink" -version = "0.3.31" +version = "0.3.32" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e575fab7d1e0dcb8d0c7bcf9a63ee213816ab51902e6d244a95819acacf1d4f7" +checksum = "c39754e157331b013978ec91992bde1ac089843443c49cbc7f46150b0fad0893" [[package]] name = "futures-task" -version = "0.3.31" +version = "0.3.32" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f90f7dce0722e95104fcb095585910c0977252f286e354b5e3bd38902cd99988" +checksum = "037711b3d59c33004d3856fbdc83b99d4ff37a24768fa1be9ce3538a1cde4393" [[package]] name = "futures-util" -version = "0.3.31" +version = "0.3.32" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9fa08315bb612088cc391249efdc3bc77536f16c91f6cf495e6fbe85b20a4a81" +checksum = "389ca41296e6190b48053de0321d02a77f32f8a5d2461dd38762c0593805c6d6" dependencies = [ "futures-channel", "futures-core", @@ -499,7 +493,6 @@ dependencies = [ "futures-task", "memchr", "pin-project-lite", - "pin-utils", "slab", ] @@ -548,9 +541,9 @@ dependencies = [ [[package]] name = "gimli" -version = "0.28.1" +version = "0.32.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4271d37baee1b8c7e4b708028c57d816cf9d2434acb33a549475f78c181f6253" +checksum = "e629b9b98ef3dd8afe6ca2bd0f89306cec16d43d907889945bc5d6687f2f13c7" [[package]] name = "hashbrown" @@ -560,9 +553,9 @@ checksum = "e5274423e17b7c9fc20b6e7e208532f9b19825d82dfd615708b70edd83df41f1" [[package]] name = "hermit-abi" -version = "0.3.3" +version = "0.5.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d77f7ec81a6d05a3abb01ab6eb7590f6083d08449fe5a1c8b1e620283546ccb7" +checksum = "fc0fef456e4baa96da950455cd02c081ca953b141298e41db3fc7e36b1da849c" [[package]] name = "hex" @@ -609,10 +602,11 @@ dependencies = [ [[package]] name = "js-sys" -version = "0.3.69" +version = "0.3.91" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "29c15563dc2726973df627357ce0c9ddddbea194836909d655df6a75d2cf296d" +checksum = "b49715b7073f385ba4bc528e5747d02e66cb39c6146efb66b781f131f0fb399c" dependencies = [ + "once_cell", "wasm-bindgen", ] @@ -627,15 +621,15 @@ dependencies = [ [[package]] name = "lazy_static" -version = "1.4.0" +version = "1.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646" +checksum = "bbd2bcb4c963f2ddae06a2efc7e9f3591312473c50c6685e1f298068316e66fe" [[package]] name = "libc" -version = "0.2.181" +version = "0.2.182" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "459427e2af2b9c839b132acb702a1c654d95e10f8c326bfc2ad11310e458b1c5" +checksum = "6800badb6cb2082ffd7b6a67e6125bb39f18782f793520caee8cb8846be06112" [[package]] name = "lock_api" @@ -648,9 +642,29 @@ dependencies = [ [[package]] name = "log" -version = "0.4.20" +version = "0.4.29" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b5e6163cb8c49088c2c36f57875e58ccd8c87c7427f7fbd50ea6710b2f3f2e8f" +checksum = "5e5032e24019045c762d3c0f28f5b6b8bbf38563a65908389bf7978758920897" + +[[package]] +name = "m_security" +version = "0.0.1" +dependencies = [ + "aes-gcm", + "argon2", + "blake3", + "chacha20poly1305", + "flutter_rust_bridge", + "hex", + "hkdf", + "log", + "rand", + "sha2", + "sha3", + "thiserror", + "zeroize", + "zstd", +] [[package]] name = "md-5" @@ -664,24 +678,24 @@ dependencies = [ [[package]] name = "memchr" -version = "2.6.4" +version = "2.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f665ee40bc4a3c5590afb1e9677db74a508659dfd71e126420da8274909a0167" +checksum = "f8ca58f447f06ed17d5fc4043ce1b10dd205e060fb3ce5b979b8ed8e59ff3f79" [[package]] name = "miniz_oxide" -version = "0.7.1" +version = "0.8.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e7810e0be55b428ada41041c41f32c9f1a42817901b4ccf45fa3d4b6561e74c7" +checksum = "1fa76a2c86f704bdb222d66965fb3d63269ce38518b83cb0575fca855ebb6316" dependencies = [ - "adler", + "adler2", ] [[package]] name = "num_cpus" -version = "1.16.0" +version = "1.17.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4161fcb6d602d4d2081af7c3a45852d875a03dd337a6bfdd6e06407b61342a43" +checksum = "91df4bbde75afed763b708b7eee1e8e7651e02d97f6d5dd763e89367e957b23b" dependencies = [ "hermit-abi", "libc", @@ -689,18 +703,18 @@ dependencies = [ [[package]] name = "object" -version = "0.32.1" +version = "0.37.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9cf5f9dd3933bd50a9e1f149ec995f39ae2c496d31fd772c1fd45ebc27e902b0" +checksum = "ff76201f031d8863c38aa7f905eca4f53abbfa15f609db4277d44cd8938f33fe" dependencies = [ "memchr", ] [[package]] name = "once_cell" -version = "1.18.0" +version = "1.21.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dd8b5dd2ae5ed71462c540258bedcb51965123ad7e7ccf4b9a8cafaa4a63576d" +checksum = "42f5e15c9953c5e4ccceeb2e7382a716482c34515315f7b03532b8b4e8393d2d" [[package]] name = "opaque-debug" @@ -745,15 +759,9 @@ dependencies = [ [[package]] name = "pin-project-lite" -version = "0.2.13" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8afb450f006bf6385ca15ef45d71d2288452bc3683ce2e2cacc0d18e4be60b58" - -[[package]] -name = "pin-utils" -version = "0.1.0" +version = "0.2.17" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184" +checksum = "a89322df9ebe1c1578d689c92318e070967d1042b512afbe49518723f4e6d5cd" [[package]] name = "pkg-config" @@ -810,9 +818,9 @@ dependencies = [ [[package]] name = "quote" -version = "1.0.44" +version = "1.0.45" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "21b2ebcf727b7760c461f091f9f0f539b77b8e87f2fd88131e7f1b433b3cece4" +checksum = "41f2619966050689382d2b44f664f4bc593e129785a36d6ee376ddf37259b924" dependencies = [ "proc-macro2", ] @@ -864,9 +872,9 @@ dependencies = [ [[package]] name = "regex" -version = "1.10.2" +version = "1.12.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "380b951a9c5e80ddfd6136919eef32310721aa4aacd4889a8d39124b026ab343" +checksum = "e10754a14b9137dd7b1e3e5b0493cc9171fdd105e0ab477f51b72e7f3ac0e276" dependencies = [ "aho-corasick", "memchr", @@ -876,9 +884,9 @@ dependencies = [ [[package]] name = "regex-automata" -version = "0.4.3" +version = "0.4.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5f804c7828047e88b2d32e2d7fe5a105da8ee3264f01902f796c8e067dc2483f" +checksum = "6e1dd4122fc1595e8162618945476892eefca7b88c52820e74af6262213cae8f" dependencies = [ "aho-corasick", "memchr", @@ -887,35 +895,21 @@ dependencies = [ [[package]] name = "regex-syntax" -version = "0.8.2" +version = "0.8.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c08c74e62047bb2de4ff487b251e4a92e24f48745648451635cec7d591162d9f" +checksum = "dc897dd8d9e8bd1ed8cdad82b5966c3e0ecae09fb1907d58efaa013543185d0a" [[package]] -name = "rust_lib_m_security" -version = "0.0.1" -dependencies = [ - "aes-gcm", - "argon2", - "blake3", - "chacha20poly1305", - "flutter_rust_bridge", - "hex", - "hkdf", - "log", - "rand", - "sha2", - "sha3", - "thiserror", - "zeroize", - "zstd", -] +name = "rustc-demangle" +version = "0.1.27" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b50b8869d9fc858ce7266cce0194bd74df58b9d0e3f6df3a9fc8eb470d95c09d" [[package]] -name = "rustc-demangle" -version = "0.1.23" +name = "rustversion" +version = "1.0.22" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d626bb9dae77e28219937af045c257c28bfd3f69333c512553507f5f9798cb76" +checksum = "b39cdef0fa800fc44525c84ccb54a029961a8215f9619753635a9c0d2538d46d" [[package]] name = "scopeguard" @@ -952,12 +946,9 @@ checksum = "0fda2ff0d084019ba4d7c6f371c95d8fd75ce3524c3cb8fb653a3023f6323e64" [[package]] name = "slab" -version = "0.4.9" +version = "0.4.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8f92a496fb766b417c996b9c5e57daf2f7ad3b0bebe1ccfca4856390e3d3bb67" -dependencies = [ - "autocfg", -] +checksum = "0c790de23124f9ab44544d7ac05d60440adc586479ce501c1d6d7da3cd8c9cf5" [[package]] name = "smallvec" @@ -973,9 +964,9 @@ checksum = "13c2bddecc57b384dee18652358fb23172facb8a2c51ccc10d74c157bdea3292" [[package]] name = "syn" -version = "2.0.115" +version = "2.0.117" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6e614ed320ac28113fa64972c4262d5dbc89deacdfd00c34a3e4cea073243c12" +checksum = "e665b8803e7b1d2a727f4023456bbbbe74da67099c585258af0ad9c5013b9b99" dependencies = [ "proc-macro2", "quote", @@ -1013,26 +1004,24 @@ dependencies = [ [[package]] name = "tokio" -version = "1.34.0" +version = "1.50.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d0c014766411e834f7af5b8f4cf46257aab4036ca95e9d2c144a10f59ad6f5b9" +checksum = "27ad5e34374e03cfffefc301becb44e9dc3c17584f414349ebe29ed26661822d" dependencies = [ - "backtrace", - "num_cpus", "pin-project-lite", ] [[package]] name = "typenum" -version = "1.17.0" +version = "1.19.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "42ff0bf0c66b8238c6f3b578df37d0b7848e55df8577b3f74f92a69acceeb825" +checksum = "562d481066bde0658276a35467c4af00bdc6ee726305698a55b86e61d7ad82bb" [[package]] name = "unicode-ident" -version = "1.0.12" +version = "1.0.24" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3354b9ac3fae1ff6755cb6db53683adb661634f67557942dea4facebec0fee4b" +checksum = "e6e4313cd5fcd3dad5cafa179702e2b244f760991f45397d14d4ebf38247da75" [[package]] name = "universal-hash" @@ -1046,9 +1035,9 @@ dependencies = [ [[package]] name = "version_check" -version = "0.9.4" +version = "0.9.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "49874b5167b65d7193b8aba1567f5c7d93d001cafc34600cee003eda787e483f" +checksum = "0b928f33d975fc6ad9f86c8f283853ad26bdd5b10b7f1542aa2fa15e2289105a" [[package]] name = "wasi" @@ -1067,46 +1056,36 @@ dependencies = [ [[package]] name = "wasm-bindgen" -version = "0.2.92" +version = "0.2.114" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4be2531df63900aeb2bca0daaaddec08491ee64ceecbee5076636a3b026795a8" +checksum = "6532f9a5c1ece3798cb1c2cfdba640b9b3ba884f5db45973a6f442510a87d38e" dependencies = [ "cfg-if", - "wasm-bindgen-macro", -] - -[[package]] -name = "wasm-bindgen-backend" -version = "0.2.92" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "614d787b966d3989fa7bb98a654e369c762374fd3213d212cfc0251257e747da" -dependencies = [ - "bumpalo", - "log", "once_cell", - "proc-macro2", - "quote", - "syn", + "rustversion", + "wasm-bindgen-macro", "wasm-bindgen-shared", ] [[package]] name = "wasm-bindgen-futures" -version = "0.4.42" +version = "0.4.64" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "76bc14366121efc8dbb487ab05bcc9d346b3b5ec0eaa76e46594cabbe51762c0" +checksum = "e9c5522b3a28661442748e09d40924dfb9ca614b21c00d3fd135720e48b67db8" dependencies = [ "cfg-if", + "futures-util", "js-sys", + "once_cell", "wasm-bindgen", "web-sys", ] [[package]] name = "wasm-bindgen-macro" -version = "0.2.92" +version = "0.2.114" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a1f8823de937b71b9460c0c34e25f3da88250760bec0ebac694b49997550d726" +checksum = "18a2d50fcf105fb33bb15f00e7a77b772945a2ee45dcf454961fd843e74c18e6" dependencies = [ "quote", "wasm-bindgen-macro-support", @@ -1114,28 +1093,31 @@ dependencies = [ [[package]] name = "wasm-bindgen-macro-support" -version = "0.2.92" +version = "0.2.114" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e94f17b526d0a461a191c78ea52bbce64071ed5c04c9ffe424dcb38f74171bb7" +checksum = "03ce4caeaac547cdf713d280eda22a730824dd11e6b8c3ca9e42247b25c631e3" dependencies = [ + "bumpalo", "proc-macro2", "quote", "syn", - "wasm-bindgen-backend", "wasm-bindgen-shared", ] [[package]] name = "wasm-bindgen-shared" -version = "0.2.92" +version = "0.2.114" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "af190c94f2773fdb3729c55b007a722abb5384da03bc0986df4c289bf5567e96" +checksum = "75a326b8c223ee17883a4251907455a2431acc2791c98c26279376490c378c16" +dependencies = [ + "unicode-ident", +] [[package]] name = "web-sys" -version = "0.3.66" +version = "0.3.91" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "50c24a44ec86bb68fbecd1b3efed7e85ea5621b39b35ef2766b66cd984f8010f" +checksum = "854ba17bb104abfb26ba36da9729addc7ce7f06f5c0f90f3c391f8461cca21f9" dependencies = [ "js-sys", "wasm-bindgen", @@ -1155,18 +1137,18 @@ checksum = "d7249219f66ced02969388cf2bb044a09756a083d0fab1e566056b04d9fbcaa5" [[package]] name = "zerocopy" -version = "0.8.39" +version = "0.8.40" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "db6d35d663eadb6c932438e763b262fe1a70987f9ae936e60158176d710cae4a" +checksum = "a789c6e490b576db9f7e6b6d661bcc9799f7c0ac8352f56ea20193b2681532e5" dependencies = [ "zerocopy-derive", ] [[package]] name = "zerocopy-derive" -version = "0.8.39" +version = "0.8.40" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4122cd3169e94605190e77839c9a40d40ed048d305bfdc146e7df40ab0f3e517" +checksum = "f65c489a7071a749c849713807783f70672b28094011623e200cb86dcb835953" dependencies = [ "proc-macro2", "quote", diff --git a/rust/Cargo.toml b/rust/Cargo.toml index 073dc92..c848c5c 100644 --- a/rust/Cargo.toml +++ b/rust/Cargo.toml @@ -1,5 +1,5 @@ [package] -name = "rust_lib_m_security" +name = "m_security" version = "0.0.1" edition = "2021" diff --git a/windows/CMakeLists.txt b/windows/CMakeLists.txt index dd5bafb..7515e9f 100644 --- a/windows/CMakeLists.txt +++ b/windows/CMakeLists.txt @@ -9,7 +9,7 @@ set(PROJECT_NAME "m_security") project(${PROJECT_NAME} LANGUAGES CXX) include("../cargokit/cmake/cargokit.cmake") -apply_cargokit(${PROJECT_NAME} ../rust rust_lib_m_security "") +apply_cargokit(${PROJECT_NAME} ../rust m_security "") # List of absolute paths to libraries that should be bundled with the plugin. # This list could contain prebuilt libraries, or libraries created by an From 72633383e8781df20fad77c913740121db5ad31c Mon Sep 17 00:00:00 2001 From: Adel HB Date: Fri, 6 Mar 2026 16:33:10 +0100 Subject: [PATCH 5/6] Improved README and CONTRIBUTING files to fit current project --- CONTRIBUTING.md | 291 ++++++++++++++++++++++++++++++------------ README.md | 333 ++++++++++++++++++++++++++++++------------------ 2 files changed, 413 insertions(+), 211 deletions(-) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 45fe9d8..2743bad 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -1,6 +1,6 @@ # Contributing to M-Security -Thank you for your interest in contributing to M-Security! This guide will help you get started. +Thank you for your interest in contributing to M-Security! This project is built and maintained by the **Dev Department** of [MicroClub](https://github.com/MicroClub-USTHB) at USTHB. This guide covers everything you need to get started. ## Table of Contents @@ -14,6 +14,17 @@ Thank you for your interest in contributing to M-Security! This guide will help - [Submitting a Pull Request](#submitting-a-pull-request) - [Security](#security) +## Project Vision + +M-Security aims to be a complete security toolkit for Flutter. The current release (v0.0.1) provides the cryptographic foundation. Future releases will build on top of it: + +1. **Cryptographic primitives** (v0.0.1, current): AEAD encryption, hashing, password hashing, key derivation +2. **Memory and performance**: Zero-copy stream processing (64 KB chunks for large files), stealth storage for ephemeral secrets in Rust-managed memory +3. **Secure storage**: Encrypted Virtual File System (`.vault` container with random-access decryption), compression-then-encryption pipeline (Zstd/Brotli + AEAD), secure file shredding +4. **Hardware integration**: Key wrap with Secure Enclave (iOS) / KeyStore (Android), biometric unlock flow (FaceID/Fingerprint), native Swift/Kotlin bridge layer + +Contributions to any of these areas are welcome. If you want to work on an upcoming feature, open an issue first to discuss the approach. + ## Code of Conduct By participating in this project, you agree to maintain a respectful and inclusive environment. Be kind, constructive, and professional in all interactions. @@ -35,37 +46,44 @@ By participating in this project, you agree to maintain a respectful and inclusi ### Prerequisites -- **Rust** (stable toolchain): - ```bash - curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh - ``` -- **Flutter SDK** (stable channel) with Dart SDK ^3.10.8 -- **Flutter Rust Bridge codegen**: - ```bash - cargo install flutter_rust_bridge_codegen - ``` -- **Platform-specific tools**: - - **macOS/iOS**: Xcode with command line tools - - **Android**: Android NDK (r27c recommended) - - **Linux**: `clang`, `cmake`, `ninja-build`, `pkg-config`, `libgtk-3-dev` - - **Windows**: Visual Studio Build Tools + LLVM +| Tool | Required For | +|------|-------------| +| [Rust](https://rustup.rs/) (stable) | Crypto core compilation | +| [Flutter SDK](https://docs.flutter.dev/get-started/install) (stable) | Dart SDK ^3.10.8 | +| [flutter_rust_bridge_codegen](https://cjycode.com/flutter_rust_bridge/) | FFI binding generation | + +Install Rust and FRB codegen: + +```bash +curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh +cargo install flutter_rust_bridge_codegen +``` + +**Platform-specific tools:** + +| Platform | Requirements | +|----------|-------------| +| macOS / iOS | Xcode with command line tools (`xcode-select --install`) | +| Android | Android NDK (r27c recommended, installed via Android Studio) | +| Linux | `sudo apt install clang cmake ninja-build pkg-config libgtk-3-dev` | +| Windows | Visual Studio Build Tools + LLVM | ### Building the Project ```bash -# Install Flutter dependencies +# 1. Install Flutter dependencies flutter pub get -# Build the Rust library +# 2. Build the Rust library (verifies Rust code compiles) cd rust && cargo build && cd .. -# Generate FFI bindings +# 3. Generate FFI bindings (Dart to Rust) flutter_rust_bridge_codegen generate -# Generate Freezed data classes +# 4. Generate Freezed data classes dart run build_runner build --delete-conflicting-outputs -# Run the example app +# 5. Run the example app (requires a device/simulator) cd example && flutter run ``` @@ -73,36 +91,78 @@ cd example && flutter run ``` M-Security/ -├── lib/ # Dart public API -│ ├── m_security.dart # Main entry point (exports) +├── lib/ # Dart public API +│ ├── m_security.dart # Barrel export (public surface) │ └── src/ -│ ├── encryption/ # AES-GCM, ChaCha20 service wrappers -│ ├── hashing/ # Argon2id wrapper -│ ├── kdf/ # HKDF wrapper -│ └── rust/ # Generated FFI bindings (do not edit) -├── rust/ # Rust crypto core +│ ├── encryption/ +│ │ ├── aes_gcm.dart # AesGcmService wrapper +│ │ └── chacha20.dart # Chacha20Service wrapper +│ ├── hashing/ +│ │ └── argon2.dart # argon2IdHash/Verify with preset defaults +│ ├── kdf/ +│ │ └── hkdf.dart # MHKDF wrapper class +│ └── rust/ # Auto-generated FRB bindings (DO NOT EDIT) +│ ├── frb_generated.dart # RustLib.init() entry point +│ ├── api/ # Generated Dart FFI functions +│ └── core/ # Generated Dart types +├── rust/ # Rust crypto core +│ ├── Cargo.toml # Crate config, dependencies, lints │ └── src/ -│ ├── api/ # Public API (scanned by FRB) -│ │ ├── encryption/ # AES-GCM, ChaCha20, Noop -│ │ ├── hashing/ # Argon2, BLAKE3, SHA-3 -│ │ └── kdf/ # HKDF-SHA256 -│ └── core/ # Internal utilities -│ ├── secret.rs # SecretBuffer with ZeroizeOnDrop -│ ├── traits.rs # Encryption, Hasher, Kdf traits -│ ├── error.rs # CryptoError enum -│ └── rng.rs # Random number generation -├── cargokit/ # Rust build system integration (Cargokit) -├── integration_test/ # Dart integration tests -├── example/ # Flutter example app -└── .github/workflows/ # CI pipeline +│ ├── lib.rs # Crate root +│ ├── frb_generated.rs # FRB-generated Rust glue +│ ├── api/ # Public API (scanned by FRB) +│ │ ├── mod.rs +│ │ ├── error.rs # CryptoError enum (thiserror) +│ │ ├── encryption/ +│ │ │ ├── mod.rs # CipherHandle, encrypt/decrypt, key gen +│ │ │ ├── aes_gcm.rs # AES-256-GCM implementation +│ │ │ ├── chacha20.rs # ChaCha20-Poly1305 implementation +│ │ │ └── noop.rs # Testing-only cipher (behind `testing` feature) +│ │ ├── hashing/ +│ │ │ ├── mod.rs # HasherHandle, blake3_hash, sha3_hash +│ │ │ ├── argon2.rs # Argon2id with presets +│ │ │ ├── blake3.rs # BLAKE3 implementation +│ │ │ └── sha3.rs # SHA-3-256 implementation +│ │ └── kdf/ +│ │ ├── mod.rs +│ │ └── hkdf.rs # HKDF-SHA256 (derive, extract, expand) +│ └── core/ # Internal utilities (not exposed to Dart) +│ ├── mod.rs +│ ├── error.rs # CryptoError definition +│ ├── traits.rs # Encryption, Hasher, Kdf traits +│ ├── secret.rs # SecretBuffer with ZeroizeOnDrop +│ ├── rng.rs # CSPRNG (OsRng) key/nonce generation +│ └── format.rs # MSEC format header for encrypted data +├── cargokit/ # Build system: compiles Rust during Flutter build +├── android/ # Android plugin (ffiPlugin + cargokit) +├── ios/ # iOS plugin (CocoaPods + cargokit) +├── macos/ # macOS plugin (CocoaPods + cargokit) +├── linux/ # Linux plugin (CMake + cargokit) +├── windows/ # Windows plugin (CMake + cargokit) +├── example/ # Flutter example app +├── integration_test/ # Dart integration tests +│ ├── aes_gcm_test.dart # AES-256-GCM (6 tests) +│ ├── chacha20_test.dart # ChaCha20-Poly1305 (7 tests) +│ ├── hashing_test.dart # BLAKE3 + SHA-3 (11 tests) +│ ├── argon2_test.dart # Argon2id (6 tests) +│ └── hkdf_test.dart # HKDF-SHA256 with RFC 5869 vectors (14 tests) +├── .github/workflows/ci.yml # CI: lint, test, build (Android, iOS, Linux) +├── flutter_rust_bridge.yaml # FRB codegen config +├── CONTRIBUTING.md +├── RELEASE_GUIDE.md +├── CHANGELOG.md +├── LICENSE # MIT +└── README.md ``` ### Key Concepts -- **`rust/src/api/`** — Everything in this directory is scanned by Flutter Rust Bridge and exposed to Dart. This is where new cryptographic primitives should be added. -- **`rust/src/core/`** — Internal Rust utilities. Not exposed to Dart. -- **`lib/src/rust/`** — Auto-generated by FRB. **Never edit these files manually.** -- **`lib/src/encryption/`, `lib/src/hashing/`, `lib/src/kdf/`** — Dart wrapper services providing a clean, idiomatic API on top of the generated FFI bindings. +- **`rust/src/api/`** contains everything scanned by Flutter Rust Bridge and exposed to Dart. New cryptographic primitives go here. +- **`rust/src/core/`** holds internal Rust utilities not exposed to Dart. It houses the `Encryption`, `Hasher`, and `Kdf` traits that all implementations must satisfy, plus `SecretBuffer` for secure memory. +- **`lib/src/rust/`** is auto-generated by FRB. **Never edit these files manually.** They are regenerated with `flutter_rust_bridge_codegen generate`. +- **`lib/src/encryption/`, `hashing/`, `kdf/`** are hand-written Dart wrapper services that provide a clean, idiomatic API on top of the generated FFI bindings. +- **`lib/m_security.dart`** is the barrel export. Only types and functions exported here are part of the public API. +- **`cargokit/`** is the build system that compiles Rust code automatically during `flutter build`. It integrates with Gradle (Android), CocoaPods (iOS/macOS), and CMake (Linux/Windows). ## Making Changes @@ -117,35 +177,67 @@ git checkout -b / ``` Branch types: -- `feat/` — New feature or algorithm -- `fix/` — Bug fix -- `refactor/` — Code restructuring -- `docs/` — Documentation changes -- `ci/` — CI/CD pipeline changes -- `test/` — Test additions or fixes + +| Prefix | Use | +|--------|-----| +| `feat/` | New feature or algorithm | +| `fix/` | Bug fix | +| `refactor/` | Code restructuring | +| `docs/` | Documentation changes | +| `ci/` | CI/CD pipeline changes | +| `test/` | Test additions or fixes | ### Adding a New Cryptographic Primitive -1. **Rust implementation** — Add your module under `rust/src/api//`. -2. **Implement the appropriate trait** from `rust/src/core/traits.rs` (`Encryption`, `Hasher`, or `Kdf`). -3. **Use `SecretBuffer`** for all key material (ensures `ZeroizeOnDrop`). -4. **Write Rust unit tests** in the same file using `#[cfg(test)]` module. -5. **Regenerate FFI bindings**: `flutter_rust_bridge_codegen generate`. -6. **Create a Dart wrapper** in `lib/src//` following existing patterns. -7. **Export it** from `lib/m_security.dart`. -8. **Write integration tests** in `integration_test/`. +1. **Implement in Rust.** Add your module under `rust/src/api//`. +2. **Implement the appropriate trait** from `rust/src/core/traits.rs`: + - `Encryption` for ciphers (requires `encrypt`, `decrypt`, `algorithm_id`) + - `Hasher` for hash functions (requires `update`, `reset`, `finalize`, `algorithm_id`) + - `Kdf` for key derivation (requires `derive`, `algorithm_id`) +3. **Use `SecretBuffer`** for all key material (ensures automatic zeroization on drop). +4. **Use `OsRng`** via `core::rng` for all randomness. Never use `thread_rng`. +5. **Return `Result`**. Never use `unwrap()` (Clippy will reject it). +6. **Write Rust unit tests** in the same file using `#[cfg(test)]`. +7. **Export the module** from the parent `mod.rs`. +8. **Regenerate FFI bindings**: + ```bash + flutter_rust_bridge_codegen generate + ``` +9. **Create a Dart wrapper** in `lib/src//` following existing patterns. +10. **Export it** from `lib/m_security.dart`. +11. **Write integration tests** in `integration_test/`. + +### Adding an Opaque Handle + +If your primitive holds state (like a cipher key or hasher state): + +```rust +use flutter_rust_bridge::frb; + +#[frb(opaque)] +pub struct MyHandle { + inner: Box, +} +``` + +This ensures the handle is never serialized across FFI. Dart holds a pointer only. ## Coding Standards ### Rust -- **No `unwrap()` in FFI-visible code** — The project enforces `clippy::unwrap_used = "deny"`. Use `Result` for all fallible operations. +- **No `unwrap()` in FFI-visible code.** Enforced by `[lints.clippy] unwrap_used = "deny"` in `Cargo.toml`. Use `Result` for all fallible operations. `unwrap()` is allowed in `#[cfg(test)]` modules only. - **Derive `ZeroizeOnDrop`** on all structs holding key material. +- **Use `thiserror`** for error types. All errors map to `CryptoError` variants. +- **`panic = "abort"` in release.** Panics must not cross FFI. This is enforced in `Cargo.toml`'s `[profile.release]`. - **Run Clippy** before committing: ```bash cd rust && cargo clippy --all-targets -- -D warnings ``` -- Use `thiserror` for error types. +- **Format code**: + ```bash + cd rust && cargo fmt + ``` ### Dart @@ -154,16 +246,24 @@ Branch types: ```bash dart analyze lib/ integration_test/ ``` +- Format code: + ```bash + dart format lib/ integration_test/ + ``` -### General +### Commit Messages -- Keep commits atomic — one logical change per commit. -- Write clear commit messages following [Conventional Commits](https://www.conventionalcommits.org/): - ``` - feat(encryption): add XChaCha20-Poly1305 cipher - fix(argon2): correct memory allocation on mobile preset - docs: update README with new algorithm table - ``` +Follow [Conventional Commits](https://www.conventionalcommits.org/): + +``` +feat(encryption): add XChaCha20-Poly1305 cipher +fix(argon2): correct memory allocation on mobile preset +docs: update README with new algorithm table +test(hkdf): add RFC 5869 test case 3 +ci: add Windows build job +``` + +Keep commits atomic, with one logical change per commit. ## Testing @@ -173,9 +273,11 @@ Branch types: cd rust && cargo test ``` +There are 79 unit tests covering all algorithms, including NIST and RFC test vectors (RFC 8439 for ChaCha20, RFC 5869 for HKDF). + ### Dart Integration Tests -Integration tests require a running device or simulator: +Integration tests require a running device or simulator. From the **project root**: ```bash cd example @@ -186,23 +288,35 @@ flutter test integration_test/argon2_test.dart flutter test integration_test/hkdf_test.dart ``` +There are 44 integration tests across 5 files covering all features. + ### CI Pipeline -All pull requests must pass the CI pipeline, which runs: +All pull requests must pass the CI pipeline (`.github/workflows/ci.yml`), which runs: -1. Rust lint (Clippy) and tests -2. Dart codegen and static analysis -3. Platform builds (Android, iOS, Linux) +| Job | Runner | What it does | +|-----|--------|-------------| +| **Rust** | `ubuntu-latest` | `cargo clippy -- -D warnings` + `cargo test` | +| **Dart** | `ubuntu-latest` | FRB codegen + `build_runner` + `dart analyze` | +| **Android** | `ubuntu-latest` | Full APK build (ARM64 + ARMv7, NDK r27c) | +| **iOS** | `macos-latest` | Simulator debug build (ARM64 + ARM64-sim) | +| **Linux** | `ubuntu-latest` | Release build with GTK-3 | + +The CI is triggered on pushes and PRs to `main` and `dev` branches. ## Submitting a Pull Request -1. **Ensure all tests pass** locally (both Rust and Dart). +1. **Ensure all tests pass** locally: + ```bash + cd rust && cargo clippy --all-targets -- -D warnings && cargo test && cd .. + dart analyze lib/ integration_test/ + ``` 2. **Push** your branch to your fork: ```bash git push origin ``` 3. **Open a PR** against the `dev` branch on the upstream repository. -4. **Fill in the PR template** with: +4. **Fill in the PR description** with: - A clear description of the change - Related issue numbers (if any) - Testing steps @@ -211,19 +325,28 @@ All pull requests must pass the CI pipeline, which runs: ### PR Checklist -- [ ] Code compiles without warnings (`cargo clippy`, `dart analyze`) -- [ ] All existing tests pass +- [ ] Rust code compiles without warnings (`cargo clippy --all-targets -- -D warnings`) +- [ ] Dart code analyzes clean (`dart analyze lib/ integration_test/`) +- [ ] All existing Rust tests pass (`cargo test`) +- [ ] All existing integration tests pass - [ ] New tests added for new functionality +- [ ] FRB bindings regenerated if Rust API changed (`flutter_rust_bridge_codegen generate`) +- [ ] Public API exported from `lib/m_security.dart` if adding new user-facing types - [ ] Documentation updated if public API changed -- [ ] CHANGELOG.md updated under an `## Unreleased` section +- [ ] `CHANGELOG.md` updated under an `## Unreleased` section - [ ] Commit messages follow Conventional Commits ## Security -If you discover a security vulnerability, **do not open a public issue**. Instead, please report it privately by emailing the maintainers or using [GitHub Security Advisories](https://github.com/MicroClub-USTHB/M-Security/security/advisories/new). +If you discover a security vulnerability, **do not open a public issue**. Instead, report it privately using [GitHub Security Advisories](https://github.com/MicroClub-USTHB/M-Security/security/advisories/new). + +### Cryptographic Code Guidelines + +Cryptographic code requires extra scrutiny. All contributions touching crypto must follow these rules: -Cryptographic code requires extra scrutiny: -- Never introduce `unsafe` blocks without justification and review. -- All key material must be zeroized on drop. -- Never expose raw key bytes across the FFI boundary. -- Use `OsRng` for all random number generation (never `thread_rng` or similar). +- **Never introduce `unsafe` blocks** without justification and review. +- **All key material must use `SecretBuffer`** (`rust/src/core/secret.rs`) which derives `ZeroizeOnDrop`. +- **Never expose raw key bytes** across the FFI boundary. Use `#[frb(opaque)]` handles. +- **Use `OsRng`** (via `core::rng`) for all random number generation. Never use `thread_rng` or similar. +- **All errors must be explicit.** Return `Result`, never `unwrap()`. +- **Include test vectors** from official standards (NIST, RFC) when implementing new algorithms. diff --git a/README.md b/README.md index fe3f3a8..9a4e960 100644 --- a/README.md +++ b/README.md @@ -4,217 +4,296 @@ [![CI](https://github.com/MicroClub-USTHB/M-Security/actions/workflows/ci.yml/badge.svg)](https://github.com/MicroClub-USTHB/M-Security/actions/workflows/ci.yml) [![License: MIT](https://img.shields.io/badge/License-MIT-blue.svg)](https://opensource.org/licenses/MIT) -A native Rust cryptographic SDK for Flutter. High-performance hashing, authenticated encryption, and key derivation — all implemented in Rust and exposed to Dart via [Flutter Rust Bridge](https://cjycode.com/flutter_rust_bridge/) (FRB). +A native Rust security SDK for Flutter, providing high-performance cryptographic services, secure memory management, and (coming soon) an encrypted virtual file system. All operations run in Rust through [Flutter Rust Bridge](https://cjycode.com/flutter_rust_bridge/). No Dart-level crypto, no platform channels. + +Built and maintained by the **Dev Department** of [MicroClub](https://github.com/MicroClub-USTHB), the computer science club at USTHB (University of Science and Technology Houari Boumediene, Algiers). ## Features -### Hashing +| Category | Algorithm | Highlights | +|----------|-----------|------------| +| **AEAD Encryption** | AES-256-GCM | Industry-standard, hardware-accelerated on most CPUs | +| | ChaCha20-Poly1305 | Optimized for mobile (no AES hardware needed) | +| **Hashing** | BLAKE3 | Ultra-fast, one-shot and streaming | +| | SHA-3-256 (Keccak) | NIST-standard, one-shot and streaming | +| **Password Hashing** | Argon2id | PHC winner, Mobile and Desktop presets | +| **Key Derivation** | HKDF-SHA256 | RFC 5869, extract-then-expand with domain separation | + +**Security by design:** +- All key material lives in Rust behind opaque handles; raw keys never cross FFI +- Automatic memory zeroization on drop (`ZeroizeOnDrop`) +- Nonces generated internally via OS-level CSPRNG (`OsRng`) +- AEAD tag verification prevents silent decryption of tampered data +- `panic = "abort"` in release profile, preventing undefined behavior from panics crossing FFI +- `clippy::unwrap_used = "deny"`, ensuring all operations return `Result` -| Algorithm | API | Output | -|-----------|-----|--------| -| **BLAKE3** | One-shot (`blake3_hash`) + streaming (`HasherHandle`) | 32 bytes | -| **SHA-3-256** | One-shot (`sha3_hash`) + streaming (`HasherHandle`) | 32 bytes | -| **Argon2id** | Password hash + verify, Mobile/Desktop presets | PHC string | +## Installation -### Authenticated Encryption (AEAD) +Add to your `pubspec.yaml`: -| Algorithm | Key | Nonce | Tag | Output Format | -|-----------|-----|-------|-----|---------------| -| **AES-256-GCM** | 32 B | 12 B (auto) | 16 B | `nonce \|\| ciphertext \|\| tag` | -| **ChaCha20-Poly1305** | 32 B | 12 B (auto) | 16 B | `nonce \|\| ciphertext \|\| tag` | +```yaml +dependencies: + m_security: ^0.0.1 +``` -Both ciphers use the same `CipherHandle` interface — create, encrypt, decrypt, generate key. +Then run: -### Key Derivation +```bash +flutter pub get +``` -| Algorithm | API | -|-----------|-----| -| **HKDF-SHA256** | `hkdf_derive`, `hkdf_extract`, `hkdf_expand` | +### Prerequisites -Derive multiple subkeys from a single master key using different `info` strings for domain separation. +M-Security compiles Rust code during the Flutter build. You need: -## Architecture +- **Rust toolchain** (stable): + ```bash + curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh + ``` -
- M-Security Architecture -
+- **Platform-specific tools:** -**Key design decisions:** + | Platform | Requirements | + |----------|-------------| + | Android | Android NDK (r27c recommended) | + | iOS / macOS | Xcode with command line tools | + | Linux | `clang`, `cmake`, `ninja-build`, `pkg-config`, `libgtk-3-dev` | + | Windows | Visual Studio Build Tools + LLVM | -- **Opaque handles** — Crypto state lives in Rust behind `#[frb(opaque)]` handles (`CipherHandle`, `HasherHandle`). Dart holds a pointer, never raw key bytes. -- **Trait objects** — All implementations are behind `Box` with `Send + Sync + 'static`, allowing runtime algorithm selection. -- **Secure memory** — All key-holding structs derive `ZeroizeOnDrop`. Key material is zeroed when handles are dropped. -- **No panics across FFI** — `clippy::unwrap_used = "deny"`, `panic = "abort"` in release. All operations return `Result`. +Rust compilation is handled automatically by [Cargokit](https://github.com/nickhudson/cargokit) during `flutter build` / `flutter run`. -## Dart Usage +## Getting Started -### AES-256-GCM +Initialize the Rust library once at app startup: ```dart -import 'package:m_security/src/encryption/aes_gcm.dart'; +import 'package:m_security/m_security.dart'; -final aes = AesGcmService(); -await aes.initWithRandomKey(); +Future main() async { + WidgetsFlutterBinding.ensureInitialized(); + await RustLib.init(); + runApp(const MyApp()); +} +``` -final encrypted = await aes.encryptString('hello'); -final decrypted = await aes.decryptString(encrypted); +## Usage + +All examples below use a single import: + +```dart +import 'package:m_security/m_security.dart'; ``` -### ChaCha20-Poly1305 +### AES-256-GCM Encryption ```dart -import 'package:m_security/src/encryption/chacha20.dart'; +final aes = AesGcmService(); +await aes.initWithRandomKey(); -final chacha = Chacha20Service(); -await chacha.initWithRandomKey(); +// Encrypt and decrypt raw bytes +final encrypted = await aes.encrypt(plaintext); +final decrypted = await aes.decrypt(encrypted); -final encrypted = await chacha.encryptString('hello'); -final decrypted = await chacha.decryptString(encrypted); +// Convenience: encrypt and decrypt UTF-8 strings +final ciphertext = await aes.encryptString('sensitive data'); +final original = await aes.decryptString(ciphertext); ``` -### Argon2id Password Hashing +### ChaCha20-Poly1305 Encryption ```dart -import 'package:m_security/src/hashing/argon2.dart'; +final chacha = Chacha20Service(); +await chacha.initWithRandomKey(); -// Hash (auto-selects Mobile or Desktop preset based on build flag) -final phc = await argon2IdHash(password: 'hunter2'); +// Basic encrypt and decrypt +final encrypted = await chacha.encryptString('sensitive data'); +final original = await chacha.decryptString(encrypted); -// Verify -await argon2IdVerify(phcHash: phc, password: 'hunter2'); +// With Associated Authenticated Data (AAD) +final ct = await chacha.encryptString('payload', aad: 'metadata'); +final pt = await chacha.decryptString(ct, aad: 'metadata'); ``` -### BLAKE3 / SHA-3 (One-shot) +Both ciphers output `nonce || ciphertext || tag`. Nonces (12 bytes) are auto-generated and authentication tags (16 bytes) are appended automatically. + +### Argon2id Password Hashing ```dart -import 'package:m_security/src/rust/api/hashing/blake3.dart'; -import 'package:m_security/src/rust/api/hashing/sha3.dart'; +// Hash a password (returns PHC-format string) +final hash = await argon2IdHash(password: 'hunter2'); + +// Verify a password against a hash +await argon2IdVerify(phcHash: hash, password: 'hunter2'); -final digest = await blake3Hash(data: bytes); -final sha3Digest = await sha3Hash(data: bytes); +// Explicit preset selection +final hash = await argon2IdHash( + password: 'hunter2', + preset: Argon2Preset.desktop, // 256 MiB, t=4, p=8 +); ``` -### HKDF Key Derivation +The default preset is selected at compile time: `Argon2Preset.mobile` (64 MiB, t=3, p=4) unless built with `-DIS_DESKTOP=true`. -```dart -import 'package:m_security/src/rust/api/kdf/hkdf.dart'; +### HKDF-SHA256 Key Derivation -final derived = await hkdfDerive( - ikm: masterKey, - salt: null, +```dart +// Derive a key from input key material +final key = MHKDF.derive( + ikm: masterKeyBytes, + salt: saltBytes, // optional info: Uint8List.fromList('encryption-key'.codeUnits), outputLen: 32, ); + +// Domain separation: same master key, different derived keys +final encKey = MHKDF.derive(ikm: master, info: utf8.encode('enc'), outputLen: 32); +final macKey = MHKDF.derive(ikm: master, info: utf8.encode('mac'), outputLen: 32); + +// Two-phase: extract PRK, then expand +final prk = MHKDF.extract(ikm: masterKeyBytes, salt: saltBytes); +final derived = await MHKDF.expand(prk: prk, info: infoBytes, outputLen: 32); ``` -## Rust API Reference +Output length must be between 1 and 8160 bytes (RFC 5869 limit for SHA-256: 255 * 32). -### Encryption +### BLAKE3 & SHA-3-256 Hashing -``` -create_aes256_gcm(key) → CipherHandle -create_chacha20_poly1305(key) → CipherHandle -encrypt(handle, plaintext, aad) → Vec -decrypt(handle, ciphertext, aad) → Vec -generate_aes256_gcm_key() → Vec -generate_chacha20_poly1305_key() → Vec -``` +For one-shot and streaming hashing, use the lower-level FFI API directly: -### Hashing +```dart +import 'package:m_security/src/rust/api/hashing.dart'; -``` -blake3_hash(data) → Vec -sha3_hash(data) → Vec -create_blake3() → HasherHandle -create_sha3() → HasherHandle -hasher_update(handle, data) → () -hasher_reset(handle) → () -hasher_finalize(handle) → Vec -``` +// One-shot hashing (32-byte output) +final blake3Digest = await blake3Hash(data: inputBytes); +final sha3Digest = await sha3Hash(data: inputBytes); -### Password Hashing +// Streaming: process data in chunks +final hasher = createBlake3(); // or createSha3() +await hasherUpdate(handle: hasher, data: chunk1); +await hasherUpdate(handle: hasher, data: chunk2); +final digest = await hasherFinalize(handle: hasher); -``` -argon2id_hash(password, preset) → String (PHC) -argon2id_hash_with_salt(password, salt, preset) → String (PHC) -argon2id_verify(phc_hash, password) → () +// Reset and reuse +await hasherReset(handle: hasher); ``` -Presets: `Mobile` (64 MiB, t=3, p=4) | `Desktop` (256 MiB, t=4, p=8) +## Architecture -### Key Derivation +
+ M-Security Architecture +
-``` -hkdf_derive(ikm, salt?, info, output_len) → Vec -hkdf_extract(ikm, salt?) → Vec (PRK) -hkdf_expand(prk, info, output_len) → Vec -``` -## Security +**Key design decisions:** -- All key material zeroized on Drop (`zeroize` crate with `ZeroizeOnDrop` derive) -- No `unwrap()` in FFI-visible code (`clippy::unwrap_used = "deny"`) -- `panic = "abort"` in release profile — no UB from panics crossing FFI -- Nonces generated internally via `OsRng` — callers never handle nonces -- Raw keys never cross the FFI boundary — stays behind opaque Rust handles -- AEAD tag verification prevents silent decryption of tampered data +- **Opaque handles.** `CipherHandle` and `HasherHandle` are `#[frb(opaque)]`. Dart holds a pointer, never raw key bytes. +- **Trait objects.** `Box` and `Box` with `Send + Sync + 'static` enable runtime algorithm selection. +- **SecretBuffer.** All key material is wrapped in `SecretBuffer` which derives `ZeroizeOnDrop`. Memory is zeroed when handles are dropped. +- **No panics across FFI.** `panic = "abort"` in release profile. All FFI functions return `Result`. +- **Format headers.** Encrypted data includes a `MSEC` magic header with version and algorithm identifiers for forward compatibility. -## Cross-Compilation Targets +## Rust API Reference -| Target | Platform | -|--------|----------| -| `aarch64-linux-android` | Android ARM64 | -| `armv7-linux-androideabi` | Android ARM32 | -| `aarch64-apple-ios` | iOS ARM64 | -| `aarch64-apple-ios-sim` | iOS Simulator | -| `aarch64-apple-darwin` | macOS ARM64 | -| `x86_64-apple-darwin` | macOS Intel | -| `x86_64-unknown-linux-gnu` | Linux | -| `x86_64-pc-windows-msvc` | Windows | +### Encryption (`CipherHandle`) -## Tech Stack +``` +create_aes256_gcm(key: Vec) -> Result +create_chacha20_poly1305(key: Vec) -> Result +encrypt(cipher, plaintext, aad) -> Result> +decrypt(cipher, ciphertext, aad) -> Result> +generate_aes256_gcm_key() -> Result> +generate_chacha20_poly1305_key() -> Result> +encryption_algorithm_id(cipher) -> String +``` -- **Rust** (stable) — crypto core -- **Flutter Rust Bridge** 2.11.1 — FFI code generation -- **Flutter SDK** (stable) / **Dart SDK** ^3.10.8 +### Hashing (`HasherHandle`) -## Prerequisites +``` +blake3_hash(data) -> Vec (one-shot, 32 bytes) +sha3_hash(data) -> Vec (one-shot, 32 bytes) +create_blake3() -> HasherHandle (streaming) +create_sha3() -> HasherHandle (streaming) +hasher_update(handle, data) -> Result<()> +hasher_reset(handle) -> Result<()> +hasher_finalize(handle) -> Result> +hasher_algorithm_id(handle) -> Result +``` -```bash -# Rust toolchain -curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh +### Password Hashing (Argon2id) -# FRB codegen -cargo install flutter_rust_bridge_codegen +``` +argon2id_hash(password, preset) -> Result (PHC) +argon2id_hash_with_salt(password, salt, preset) -> Result (PHC) +argon2id_verify(phc_hash, password) -> Result<()> ``` -Platform-specific: Xcode (macOS/iOS), Android NDK (Android), Visual Studio Build Tools + LLVM (Windows), `build-essential` + `libssl-dev` (Linux). +Presets: `Mobile` (64 MiB, t=3, p=4) | `Desktop` (256 MiB, t=4, p=8) -## Quick Start +### Key Derivation (HKDF-SHA256) -```bash -flutter pub get -cd rust && cargo build && cd .. -flutter_rust_bridge_codegen generate -flutter run ``` +hkdf_derive(ikm, salt?, info, output_len) -> Result> (one-shot) +hkdf_extract(ikm, salt?) -> Result> (PRK) +hkdf_expand(prk, info, output_len) -> Result> +``` + +## Platform Support + +| Platform | Target | Status | +|----------|--------|--------| +| Android | `aarch64-linux-android`, `armv7-linux-androideabi` | CI-tested | +| iOS | `aarch64-apple-ios`, `aarch64-apple-ios-sim` | CI-tested | +| macOS | `aarch64-apple-darwin`, `x86_64-apple-darwin` | Supported | +| Linux | `x86_64-unknown-linux-gnu` | CI-tested | +| Windows | `x86_64-pc-windows-msvc` | Supported | ## Testing -**Rust unit tests:** +**Rust unit tests** (79 tests including NIST/RFC test vectors): ```bash cd rust && cargo test ``` -**Dart integration tests** (requires a running device/simulator): +**Dart integration tests** (44 tests across all features, requires a running device/simulator): ```bash cd example flutter test integration_test/aes_gcm_test.dart flutter test integration_test/chacha20_test.dart flutter test integration_test/hashing_test.dart flutter test integration_test/argon2_test.dart +flutter test integration_test/hkdf_test.dart ``` +## Tech Stack + +| Component | Version | +|-----------|---------| +| Rust | stable | +| Flutter Rust Bridge | 2.11.1 | +| Dart SDK | ^3.10.8 | +| Flutter SDK | >=3.3.0 | + +**Rust crates:** `aes-gcm` 0.10, `chacha20poly1305` 0.10, `blake3` 1.8, `sha3` 0.10, `argon2` 0.5, `hkdf` 0.12, `zeroize` 1.8 + +## Roadmap + +v0.0.1 ships the cryptographic foundation. The following features are planned for future releases: + +| Feature | Description | Status | +|---------|-------------|--------| +| **Zero-copy stream processing** | Process large files (2 GB+) in 64 KB chunks via Rust pointers, keeping RAM usage constant regardless of file size | Planned | +| **Compression + encryption pipeline** | `Raw Data -> Zstd/Brotli -> AES-GCM/ChaCha20`. Reduces disk usage and increases entropy before encryption | Planned | +| **Encrypted Virtual File System (EVFS)** | Single `.vault` container with random-access decryption of individual segments, isolated from filesystem exploration | Planned | +| **Secure shredding** | Multi-pass overwrite (random noise patterns) before deleting file pointers, preventing forensic recovery | Planned | +| **Stealth storage** | Ephemeral secrets (API tokens) held in Rust-managed memory with derived-path obfuscation to resist memory dump extraction | Planned | +| **Hardware key wrap** | Master key generated in Rust, wrap key stored in Secure Enclave (iOS) / KeyStore (Android), unlocked via biometric authentication | Planned | + +## Contributing + +See [CONTRIBUTING.md](CONTRIBUTING.md) for development setup, coding standards, and PR workflow. + ## License -MIT +MIT. See [LICENSE](LICENSE) for details. + +Copyright (c) 2025 [MicroClub-USTHB](https://github.com/MicroClub-USTHB) From d280c52189a5fa48b80ab905fc114cefa26c2e17 Mon Sep 17 00:00:00 2001 From: Adel HB Date: Fri, 6 Mar 2026 16:39:47 +0100 Subject: [PATCH 6/6] Changed release version to 0.1.0 --- CHANGELOG.md | 2 +- CONTRIBUTING.md | 4 ++-- README.md | 4 ++-- example/pubspec.lock | 2 +- ios/m_security.podspec | 2 +- macos/m_security.podspec | 2 +- pubspec.yaml | 2 +- rust/Cargo.lock | 2 +- rust/Cargo.toml | 2 +- 9 files changed, 11 insertions(+), 11 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index cbdb612..d6ae61c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,4 +1,4 @@ -## 0.0.1 +## 0.1.0 Initial release of M-Security — a native Rust cryptographic SDK for Flutter. diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 2743bad..e03f81d 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -16,9 +16,9 @@ Thank you for your interest in contributing to M-Security! This project is built ## Project Vision -M-Security aims to be a complete security toolkit for Flutter. The current release (v0.0.1) provides the cryptographic foundation. Future releases will build on top of it: +M-Security aims to be a complete security toolkit for Flutter. The current release (v0.1.0) provides the cryptographic foundation. Future releases will build on top of it: -1. **Cryptographic primitives** (v0.0.1, current): AEAD encryption, hashing, password hashing, key derivation +1. **Cryptographic primitives** (v0.1.0, current): AEAD encryption, hashing, password hashing, key derivation 2. **Memory and performance**: Zero-copy stream processing (64 KB chunks for large files), stealth storage for ephemeral secrets in Rust-managed memory 3. **Secure storage**: Encrypted Virtual File System (`.vault` container with random-access decryption), compression-then-encryption pipeline (Zstd/Brotli + AEAD), secure file shredding 4. **Hardware integration**: Key wrap with Secure Enclave (iOS) / KeyStore (Android), biometric unlock flow (FaceID/Fingerprint), native Swift/Kotlin bridge layer diff --git a/README.md b/README.md index 9a4e960..49b2a85 100644 --- a/README.md +++ b/README.md @@ -33,7 +33,7 @@ Add to your `pubspec.yaml`: ```yaml dependencies: - m_security: ^0.0.1 + m_security: ^0.1.0 ``` Then run: @@ -277,7 +277,7 @@ flutter test integration_test/hkdf_test.dart ## Roadmap -v0.0.1 ships the cryptographic foundation. The following features are planned for future releases: +v0.1.0 ships the cryptographic foundation. The following features are planned for future releases: | Feature | Description | Status | |---------|-------------|--------| diff --git a/example/pubspec.lock b/example/pubspec.lock index 7ce72f1..c5af00b 100644 --- a/example/pubspec.lock +++ b/example/pubspec.lock @@ -176,7 +176,7 @@ packages: path: ".." relative: true source: path - version: "0.0.1" + version: "0.1.0" matcher: dependency: transitive description: diff --git a/ios/m_security.podspec b/ios/m_security.podspec index 5fc1365..e57b5de 100644 --- a/ios/m_security.podspec +++ b/ios/m_security.podspec @@ -4,7 +4,7 @@ # Pod::Spec.new do |s| s.name = 'm_security' - s.version = '0.0.1' + s.version = '0.1.0' s.summary = 'A high-performance cryptographic SDK for Flutter powered by native Rust via FFI.' s.description = <<-DESC A high-performance cryptographic SDK for Flutter powered by native Rust via FFI. diff --git a/macos/m_security.podspec b/macos/m_security.podspec index 22b1345..8a2e6eb 100644 --- a/macos/m_security.podspec +++ b/macos/m_security.podspec @@ -4,7 +4,7 @@ # Pod::Spec.new do |s| s.name = 'm_security' - s.version = '0.0.1' + s.version = '0.1.0' s.summary = 'A high-performance cryptographic SDK for Flutter powered by native Rust via FFI.' s.description = <<-DESC A high-performance cryptographic SDK for Flutter powered by native Rust via FFI. diff --git a/pubspec.yaml b/pubspec.yaml index 6a4d9c2..74dfd33 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -3,7 +3,7 @@ description: >- A high-performance cryptographic SDK for Flutter powered by native Rust via FFI. Provides authenticated encryption (AES-256-GCM, ChaCha20-Poly1305), modern hashing (BLAKE3, SHA-3, Argon2id), and key derivation (HKDF-SHA256) with secure memory management. -version: 0.0.1 +version: 0.1.0 homepage: https://github.com/MicroClub-USTHB/M-Security repository: https://github.com/MicroClub-USTHB/M-Security issue_tracker: https://github.com/MicroClub-USTHB/M-Security/issues diff --git a/rust/Cargo.lock b/rust/Cargo.lock index b66e884..e1b268f 100644 --- a/rust/Cargo.lock +++ b/rust/Cargo.lock @@ -648,7 +648,7 @@ checksum = "5e5032e24019045c762d3c0f28f5b6b8bbf38563a65908389bf7978758920897" [[package]] name = "m_security" -version = "0.0.1" +version = "0.1.0" dependencies = [ "aes-gcm", "argon2", diff --git a/rust/Cargo.toml b/rust/Cargo.toml index c848c5c..24cc27a 100644 --- a/rust/Cargo.toml +++ b/rust/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "m_security" -version = "0.0.1" +version = "0.1.0" edition = "2021" [lib]