MOD: code cleanup from ffi plugin to flutter rust bridge, codegen generate and flutter build macos GTG

This commit is contained in:
JohnE 2026-03-11 14:08:49 -07:00
parent 9d8c2594d8
commit a129711e4d
46 changed files with 2599 additions and 407 deletions

View File

@ -18,7 +18,7 @@ This repository contains:
* A small Rust bridge crate referencing ``ccc_rust`` via a git tag
* Generated ``flutter_rust_bridge`` bindings
* A Flutter plugin scaffold (iOS / Android / macOS)
* A Flutter plugin scaffold (iOS / Android / macOS / Linux / Windows)
* A clean Dart API surface for applications
This plugin does **not** implement cryptography itself.

View File

@ -1,7 +1,7 @@
// The Android Gradle Plugin builds the native code with the Android NDK.
group = "com.example.ccc_cryptography"
version = "1.0"
group 'com.flutter_rust_bridge.ccc_cryptography'
version '1.0'
buildscript {
repositories {
@ -11,7 +11,7 @@ buildscript {
dependencies {
// The Android Gradle Plugin knows how to build native code with the NDK.
classpath("com.android.tools.build:gradle:8.11.1")
classpath 'com.android.tools.build:gradle:7.3.0'
}
}
@ -22,42 +22,35 @@ rootProject.allprojects {
}
}
apply plugin: "com.android.library"
apply plugin: 'com.android.library'
android {
namespace = "com.example.ccc_cryptography"
if (project.android.hasProperty("namespace")) {
namespace 'com.flutter_rust_bridge.ccc_cryptography'
}
// Bumping the plugin compileSdk version requires all clients of this plugin
// Bumping the plugin compileSdkVersion requires all clients of this plugin
// to bump the version in their app.
compileSdk = 36
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 specific NDK version.
// Replace it with a version number if this plugin requires a specfic NDK version.
// (e.g. ndkVersion "23.1.7779620")
ndkVersion = android.ndkVersion
// Invoke the shared CMake build with the Android Gradle Plugin.
externalNativeBuild {
cmake {
path = "../src/CMakeLists.txt"
// The default CMake version for the Android Gradle Plugin is 3.10.2.
// https://developer.android.com/studio/projects/install-ndk#vanilla_cmake
//
// 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.
// version "3.10.2"
}
}
ndkVersion android.ndkVersion
compileOptions {
sourceCompatibility = JavaVersion.VERSION_17
targetCompatibility = JavaVersion.VERSION_17
sourceCompatibility JavaVersion.VERSION_1_8
targetCompatibility JavaVersion.VERSION_1_8
}
defaultConfig {
minSdk = 24
minSdkVersion 19
}
}
apply from: "../cargokit/gradle/plugin.gradle"
cargokit {
manifestDir = "../rust"
libname = "ccc_cryptography"
}

49
docs/README_DEV.rst Normal file
View File

@ -0,0 +1,49 @@
FRB v2
======
With flutter_rust_bridge, the Rust dependency lives in Cargo.toml, not pubspec.yaml
FRB v2 ships with Cargokit — a build helper that hooks into each platform's build
system (Gradle, Xcode, CMake) and compiles the Rust crate automatically at flutter build time.
This means:
* ccc_rust does not need a pubspec.yaml
* ccc_rust stays a pure Rust crate
* The current lum_ccc_rust entry in pubspec.yaml would be removed — it moves to rust/Cargo.toml
::
ccc_dart_plugin/
├── pubspec.yaml ← NO reference to ccc_rust here
├── rust/
│ ├── Cargo.toml ← ccc_rust referenced HERE as a Rust crate dep
│ └── src/api.rs ← thin wrappers calling ccc_rust
ccc_rust
========
The Rust crypto library remains a pure Rust crate with no Flutter or FFI-specific code.
Option 1: Build from source via Cargokit (recommended for development)
* The Rust crate references ccc_rust via a git tag in Cargo.toml
* Cargokit compiles the Rust code at build time for each platform
* No precompiled binaries are needed
Option 2: Cargokit precompiled binaries via GitHub Releases (recommended for pub.dev)
* The Rust crate is compiled into platform-specific binaries (staticlib for iOS/macOS, cdylib for Android)
* Binaries are uploaded to GitHub Releases
* Cargokit fetches the correct binary at build time based on the target platform
* This allows pub.dev users to get native performance without needing Rust or a build environment
Workflow
--------
* CI builds the Rust crate for all 5 platform targets
* CI uploads the .so/.dylib/.dll/.framework to a GitHub Release tagged with the Cargo package hash
* When consumers run flutter build, Cargokit downloads the precompiled binary instead of compiling
* If no precompiled binary exists, it falls back to source build
* Pros: Fast builds for consumers, no Rust toolchain needed, no repo bloat, built into FRB, single repo
* Cons: Requires CI pipeline to build + upload binaries
* Best for: pub.dev releases, distributing to teams without Rust installed

View File

@ -1,9 +1,9 @@
CCC Dart Plugin — Architecture & Integration Guide
====================================================
:Status: Milestone 2 (Planned)
:Depends on: ``ccc_rust`` ≥ v0.1.0
:Target: Flutter (iOS, Android, macOS)
:Status: Milestone 2 (In Progress)
:Depends on: ``ccc_rust`` ≥ v0.1.0 (ready)
:Target: Flutter (iOS, Android, macOS, Linux, Windows)
:Bridge: ``flutter_rust_bridge`` v2
Overview
@ -23,7 +23,7 @@ This repository contains:
* A small Rust bridge crate referencing ``ccc_rust`` via a git tag
* Generated ``flutter_rust_bridge`` bindings
* A Flutter plugin scaffold (iOS / Android / macOS)
* A Flutter plugin scaffold (iOS / Android / macOS / Linux / Windows)
* A clean Dart API surface for applications
This plugin does **not** implement cryptography itself.
@ -100,21 +100,25 @@ Repository Structure
ccc_dart_plugin/
├── pubspec.yaml
├── flutter_rust_bridge.yaml
├── lib/
│ ├── ccc_cryptography.dart # barrel export
│ ├── ccc_crypto.dart
│ ├── ccc_provider_catalog.dart
│ ├── ccc_self_test.dart
│ ├── ccc_exceptions.dart
│ └── src/
│ └── frb_generated.dart
│ └── frb_generated.dart # auto-generated by FRB
├── rust/
│ ├── Cargo.toml
│ └── src/
│ ├── lib.rs
│ └── api.rs
├── flutter_rust_bridge.yaml
│ └── api.rs # thin wrappers over ccc_rust
├── ios/
├── android/
├── macos/
├── linux/
├── windows/
└── test/
└── roundtrip_test.dart
@ -128,7 +132,7 @@ Rust Bridge Crate
.. code-block:: toml
[package]
name = "ccc_dart_bridge"
name = "ccc_cryptography"
version = "0.1.0"
edition = "2021"
@ -228,13 +232,19 @@ Testing Requirements
Before tagging ``v0.1.0`` of this plugin:
* Rust bridge builds for:
- iOS (aarch64-apple-ios)
- Android (arm64 + x86_64)
- macOS (aarch64)
* Flutter integration tests:
- iOS (aarch64-apple-ios, aarch64-apple-ios-sim)
- Android (aarch64-linux-android, x86_64-linux-android)
- macOS (aarch64-apple-darwin, x86_64-apple-darwin)
- Linux (x86_64-unknown-linux-gnu)
- Windows (x86_64-pc-windows-msvc)
* Unit tests (Dart-side, host platform):
- AEAD roundtrip encrypt/decrypt
- HKDF known-vector test
- X25519 key agreement test
- Provider catalog and self-test validation
- Error handling / exception mapping
* Flutter integration tests (on-device, all five platforms):
- Full init → encrypt → decrypt flow
* ``CccSelfTest.runAll()`` returns success
* No Dart-side crypto logic present
* No modification of ``ccc_rust`` source
@ -296,3 +306,11 @@ Planned enhancements after Milestone 2:
----
Related Documents
-----------------
* ``docs/milestone2_phases.rst`` — Phase-by-phase implementation
tracker with task checklists and exit criteria.
----

View File

@ -0,0 +1,574 @@
CCC Dart Plugin — Milestone 2 Implementation Phases
=====================================================
:Created: 2026-03-11
:Last Updated: 2026-03-11
:Status: In Progress
:Depends on: ``ccc_rust`` ≥ v0.1.0 (ready)
:Bridge: ``flutter_rust_bridge`` v2
:Platforms: iOS, Android, macOS, Linux, Windows
:Rust repo: ``ssh://git@10.0.5.109:j3g/lum_ccc_rust.git``
:Local override: ``/Volumes/LUM/source/letusmsg_proj/app/lum_ccc_rust``
This document tracks the implementation phases for Milestone 2 —
building the ``flutter_rust_bridge``-based Flutter plugin that exposes
``ccc_rust`` cryptographic providers to Dart.
Related Documents
~~~~~~~~~~~~~~~~~
* ``docs/ccc_fplugin_architecture_design.rst`` — Architecture & integration guide
* ``docs/ccc_rust_plan.rst`` — Master three-milestone architecture plan
* ``docs/ccc_rust_plan_phases.rst`` — Phase tracking across all milestones
* ``docs/ccc_rust_milestone2_session_state_OLD.rst`` — Earlier planning (superseded by this doc)
Preconditions (verified)
~~~~~~~~~~~~~~~~~~~~~~~~
* ``[x]`` Milestone 1 verification gate passed
* ``[x]`` Conformance vectors passed in Rust workspace
* ``[x]`` Rust target builds validated (iOS + Android)
* ``[x]`` ``cargo audit`` — no known CVEs
----
Phase Overview
--------------
====== ========================================== ========== ============
Phase Title Status Depends on
====== ========================================== ========== ============
1 Project Restructure & FRB Setup Done —
2 Rust Bridge Crate (DTOs + API) Not Started Phase 1
3 Dart API Surface Not Started Phase 2
4 Platform Build Verification Not Started Phase 3
5 Unit Tests Not Started Phase 3
6 Integration Tests & Polish Not Started Phase 4, 5
====== ========================================== ========== ============
----
Phase 1 — Project Restructure & FRB Setup
------------------------------------------
:Status: Done
**Goal:** Replace the placeholder C FFI scaffold with a
``flutter_rust_bridge`` v2 project structure.
Tasks
~~~~~
.. list-table::
:header-rows: 1
:widths: 5 60 15
* - #
- Task
- Status
* - 1.1
- Remove placeholder C source files (``src/ccc_cryptography.c``,
``src/ccc_cryptography.h``)
- ✅
* - 1.2
- Remove ``ffigen.yaml`` and generated bindings
(``lib/ccc_cryptography_bindings_generated.dart``)
- ✅
* - 1.3
- Create ``rust/`` directory with bridge crate scaffold
(``Cargo.toml``, ``src/lib.rs``, ``src/api/``); FRB directory
structure via ``flutter_rust_bridge_codegen integrate``;
set ``crate-type = ["cdylib", "staticlib"]``
- ✅
* - 1.4
- Add ``flutter_rust_bridge`` v2 dependency to ``rust/Cargo.toml``;
reference ``ccc_rust`` crates via local path deps for dev
(git deps commented for CI/release);
crate name set to ``ccc_cryptography`` to match plugin
- ✅
* - 1.5
- Create ``flutter_rust_bridge.yaml`` configuration
(``rust_input: crate::api``, ``dart_output: lib/src/rust``)
- ✅
* - 1.6
- Update ``pubspec.yaml``: replace ``ffigen`` with
``flutter_rust_bridge``, add freezed, integration_test
- ✅
* - 1.7
- Platform build configs generated by FRB integrate +
Cargokit (CMakeLists, Podspecs, Gradle)
- ✅
* - 1.8
- Run ``flutter_rust_bridge_codegen generate`` — bridge compiles;
``flutter build macos`` succeeds (42.7 MB example app)
- ✅
Exit Criteria
~~~~~~~~~~~~~
* ``flutter_rust_bridge_codegen generate`` succeeds.
* ``flutter build`` runs without errors on host (macOS).
* No C FFI scaffolding remains.
----
Phase 2 — Rust Bridge Crate (DTOs + API)
------------------------------------------
:Status: Not Started
:Depends on: Phase 1
**Goal:** Implement DTOs and thin Rust wrappers in the bridge crate that
expose all ``ccc_rust`` provider functionality across the FRB bridge.
The bridge crate lives at ``rust/`` and must not contain any cryptographic
logic — only type conversions and delegation to ``ccc_rust`` providers.
DTOs (``rust/src/dto.rs``)
~~~~~~~~~~~~~~~~~~~~~~~~~~
Bridge-visible data transfer objects with ``From<core type>`` impls:
.. list-table::
:header-rows: 1
:widths: 5 60 15
* - #
- Task
- Status
* - 2.1
- ``CapabilitiesDto`` — maps from ``ProviderCapabilities``
(provider name, algorithm availability, efficiency/reliability
scores)
- ☐
* - 2.2
- ``KemKeyPairDto`` — maps from ``KemKeyPair``
(public_key, private_key as ``Vec<u8>``)
- ☐
* - 2.3
- ``KemEncapDto`` — maps from KEM encapsulation result
(ciphertext, shared_secret)
- ☐
* - 2.4
- ``SelfTestDto`` — maps from ``SelfTestReport``
(overall pass/fail, per-algorithm results)
- ☐
* - 2.5
- ``AlgoTestResultDto`` — maps from ``AlgoTestResult``
(algorithm ID, pass/fail, diagnostic message)
- ☐
Bridge API (``rust/src/api.rs``)
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
.. list-table::
:header-rows: 1
:widths: 5 60 15
* - #
- Task
- Status
* - 2.6
- ``ccc_init()`` — register WolfSslProvider, run capability probe
- ☐
* - 2.7
- ``ccc_list_providers()`` — return registered provider names
- ☐
* - 2.8
- ``ccc_capabilities()`` / ``ccc_available_algorithms()``
— return ``CapabilitiesDto`` for a provider
- ☐
* - 2.9
- ``ccc_aead_encrypt(algorithm, key, nonce, plaintext, aad)``
— thin wrapper over provider AEAD encrypt
- ☐
* - 2.10
- ``ccc_aead_decrypt(algorithm, key, nonce, ciphertext, aad)``
— thin wrapper over provider AEAD decrypt
- ☐
* - 2.11
- ``ccc_kdf_derive(algorithm, ikm, salt, info, len)``
— thin wrapper over provider KDF
- ☐
* - 2.12
- ``ccc_mac_compute(algorithm, key, data)``
— thin wrapper over provider MAC compute
- ☐
* - 2.13
- ``ccc_mac_verify(algorithm, key, data, mac)``
— thin wrapper over provider MAC verify
- ☐
* - 2.14
- ``ccc_hash(algorithm, data)``
— thin wrapper over provider hash
- ☐
* - 2.15
- ``ccc_kem_generate_keypair(algorithm)``
— return ``KemKeyPairDto``
- ☐
* - 2.16
- ``ccc_kem_encapsulate(algorithm, public_key)``
— return ``KemEncapDto``
- ☐
* - 2.17
- ``ccc_kem_decapsulate(algorithm, private_key, ciphertext)``
— return shared secret
- ☐
* - 2.18
- ``ccc_self_test()`` — return ``SelfTestDto``
- ☐
* - 2.19
- Define bridge-visible error enum mapping ``CryptoError``
variants to structured types (``UnsupportedAlgorithm``,
``InvalidKey``, ``InvalidNonce``, ``AuthenticationFailed``,
``InternalError``)
- ☐
* - 2.20
- Run ``flutter_rust_bridge_codegen generate`` — verify all
wrappers produce valid Dart bindings
- ☐
DTO ↔ Rust Type Mapping
~~~~~~~~~~~~~~~~~~~~~~~~
======================== =================================== ========================
Bridge DTO Rust Core Type Direction
======================== =================================== ========================
``CapabilitiesDto`` ``ProviderCapabilities`` Rust → Dart
``KemKeyPairDto`` ``KemKeyPair`` Rust → Dart
``KemEncapDto`` (ciphertext, shared_secret) Rust → Dart
``SelfTestDto`` ``SelfTestReport`` Rust → Dart
``AlgoTestResultDto`` ``AlgoTestResult`` Rust → Dart
``CryptoError`` enum ``CryptoError`` Rust → Dart exception
======================== =================================== ========================
Exit Criteria
~~~~~~~~~~~~~
* All DTOs defined with ``From<>`` impls.
* All 13 bridge entry points exist in ``api.rs``.
* Codegen produces Dart bindings without warnings.
* Rust crate compiles with ``ccc_rust`` linked.
----
Phase 3 — Dart API Surface
----------------------------
:Status: Not Started
:Depends on: Phase 2
**Goal:** Build the clean Dart API layer that application code will
consume, wired to the FRB-generated bindings.
Tasks
~~~~~
.. list-table::
:header-rows: 1
:widths: 5 60 15
* - #
- Task
- Status
* - 3.1
- Create ``lib/ccc_crypto.dart`` — primary entry point class
``CccCrypto`` with all public methods:
``cccInit``, ``listProviders``, ``getCapabilities``,
``encryptAead``, ``decryptAead``, ``deriveKey``,
``computeMac``, ``verifyMac``, ``hash``,
``kemGenerateKeypair``, ``kemEncapsulate``, ``kemDecapsulate``,
``runSelfTest``
- ☐
* - 3.2
- Create ``lib/ccc_provider_catalog.dart````CccProviderCatalog``
(provider name, algorithms, efficiency/reliability scores)
- ☐
* - 3.3
- Create ``lib/ccc_self_test.dart````CccSelfTestResult``
(per-algorithm pass/fail, overall status, diagnostics)
- ☐
* - 3.4
- Create ``lib/ccc_exceptions.dart`` — structured exception
classes (``CccUnsupportedAlgorithm``, ``CccInvalidKey``,
``CccInvalidNonce``, ``CccAuthenticationFailed``,
``CccInternalError``)
- ☐
* - 3.5
- Create ``lib/ccc_algorithm_ids.dart`` — algorithm ID constants
matching Rust enum discriminants 1-to-1 (values from
``cipher_constants.dart``); no remapping
- ☐
* - 3.6
- Wire all Dart API methods to FRB-generated bindings
- ☐
* - 3.7
- Create barrel export file ``lib/ccc_cryptography.dart``
re-exporting the public API
- ☐
* - 3.8
- Remove old placeholder Dart code (``sum``, ``sumAsync``)
- ☐
Exit Criteria
~~~~~~~~~~~~~
* ``dart analyze`` reports no errors or warnings.
* Public API matches the contract in the architecture design doc.
* No crypto logic exists in Dart — orchestration only.
----
Phase 4 — Platform Build Verification
---------------------------------------
:Status: Not Started
:Depends on: Phase 3
**Goal:** Verify the Rust bridge crate cross-compiles and links
correctly on all five target platforms.
Tasks
~~~~~
.. list-table::
:header-rows: 1
:widths: 5 60 15
* - #
- Task
- Status
* - 4.1
- Build for **iOS** (``aarch64-apple-ios``,
``aarch64-apple-ios-sim``)
- ☐
* - 4.2
- Build for **Android** (``aarch64-linux-android``,
``x86_64-linux-android``)
- ☐
* - 4.3
- Build for **macOS** (``aarch64-apple-darwin``,
``x86_64-apple-darwin``)
- ☐
* - 4.4
- Build for **Linux** (``x86_64-unknown-linux-gnu``)
- ☐
* - 4.5
- Build for **Windows** (``x86_64-pc-windows-msvc``)
- ☐
* - 4.6
- Fix any platform-specific linker or NDK issues
- ☐
* - 4.7
- Verify ``flutter run`` launches on at least one
physical/emulated device per platform
- ☐
Exit Criteria
~~~~~~~~~~~~~
* ``flutter build`` succeeds for all five platforms.
* Native library is bundled correctly in each platform's output.
----
Phase 5 — Unit Tests
---------------------
:Status: Not Started
:Depends on: Phase 3
**Goal:** Verify correctness of the bridge and Dart API via
Dart-side unit tests.
Tasks
~~~~~
.. list-table::
:header-rows: 1
:widths: 5 60 15
* - #
- Task
- Status
* - 5.1
- AEAD roundtrip test — encrypt then decrypt 1 KB
(AES-256-GCM), verify plaintext equality
- ☐
* - 5.2
- AEAD roundtrip test — encrypt then decrypt 1 KB
(ChaCha20-Poly1305)
- ☐
* - 5.3
- AEAD tamper test — modify ciphertext, verify
``CccAuthenticationFailed`` is thrown
- ☐
* - 5.4
- KDF known-vector test — HKDF-SHA256 output compared against
RFC 5869 test vectors
- ☐
* - 5.5
- MAC roundtrip test — ``computeMac`` then ``verifyMac``
(HMAC-SHA256), verify returns true
- ☐
* - 5.6
- MAC tamper test — modify data after MAC, verify returns false
- ☐
* - 5.7
- Hash known-vector test — compare output against known
SHA-256 / SHA-384 / SHA-512 digests
- ☐
* - 5.8
- KEM roundtrip test — ``kemGenerateKeypair``,
``kemEncapsulate``, ``kemDecapsulate`` (X25519); verify
shared secrets match
- ☐
* - 5.9
- KEM roundtrip test — X448 keygen/encap/decap flow
- ☐
* - 5.10
- Provider catalog test — verify ``listProviders()`` returns
non-empty list, ``getCapabilities()`` returns per-algorithm
availability and scores
- ☐
* - 5.11
- Self-test validation — ``runSelfTest()`` returns overall pass
with per-algorithm results
- ☐
* - 5.12
- Error handling tests — verify each ``CccException`` subtype
is thrown for the corresponding error condition
(unsupported algorithm, invalid key, invalid nonce)
- ☐
* - 5.13
- Algorithm ID mapping test — verify Dart constants match
Rust enum discriminants (1-to-1, no drift)
- ☐
Exit Criteria
~~~~~~~~~~~~~
* All unit tests pass on host platform (macOS).
* No Dart-side crypto logic introduced by tests.
----
Phase 6 — Integration Tests & Polish
--------------------------------------
:Status: Not Started
:Depends on: Phase 4, Phase 5
**Goal:** End-to-end validation on real devices/simulators, example
app update, documentation, and release preparation.
Tasks
~~~~~
.. list-table::
:header-rows: 1
:widths: 5 60 15
* - #
- Task
- Status
* - 6.1
- Write Flutter integration tests (``integration_test/``) that
exercise the full init → encrypt → decrypt flow on-device
- ☐
* - 6.2
- Integration test: KEM keygen → encap → decap roundtrip
- ☐
* - 6.3
- Integration test: self-test API returns all-pass
- ☐
* - 6.4
- Run integration tests on iOS simulator
- ☐
* - 6.5
- Run integration tests on Android emulator
- ☐
* - 6.6
- Run integration tests on macOS
- ☐
* - 6.7
- Run integration tests on Linux
- ☐
* - 6.8
- Run integration tests on Windows
- ☐
* - 6.9
- Update example app (``example/``) — replace ``sum`` demo with
real crypto demo (encrypt/decrypt, provider listing, self-test)
- ☐
* - 6.10
- Update ``CHANGELOG.md`` for v0.1.0
- ☐
* - 6.11
- Final review — confirm no Dart crypto logic, no ``ccc_rust``
source modifications, all tests green
- ☐
* - 6.12
- Tag ``v0.1.0`` of the plugin
- ☐
Exit Criteria
~~~~~~~~~~~~~
* Integration tests pass on all five platforms.
* Example app demonstrates real cryptographic operations.
* ``CHANGELOG.md`` is updated.
* Repository tagged ``v0.1.0``.
----
Milestone 2 Verification Gate
------------------------------
*All items must be checked before the* ``v0.1.0`` *tag is cut.*
* ``[ ]`` FRB bridge API compiles and loads in Flutter plugin
* ``[ ]`` Generated Dart bindings are committed and reproducible
* ``[ ]`` All unit tests pass on host platform (macOS)
* ``[ ]`` ``flutter build ios`` succeeds
* ``[ ]`` ``flutter build apk`` succeeds
* ``[ ]`` ``flutter build macos`` succeeds
* ``[ ]`` ``flutter build linux`` succeeds
* ``[ ]`` ``flutter build windows`` succeeds
* ``[ ]`` Integration tests pass on iOS simulator
* ``[ ]`` Integration tests pass on Android emulator/device
* ``[ ]`` Integration tests pass on macOS
* ``[ ]`` Integration tests pass on Linux
* ``[ ]`` Integration tests pass on Windows
* ``[ ]`` No Dart-side crypto logic present
* ``[ ]`` No modification of ``ccc_rust`` source
* ``[ ]`` ``ccc_rust`` dependency pinned to exact commit/tag
* ``[ ]`` Plugin package tagged ``v0.1.0``
----
Milestone 3 Handoff Checklist
------------------------------
Before handing off to the LetUsMsg app team:
☐ All Phase 16 exit criteria met
☐ Milestone 2 Verification Gate passed
``CccCrypto`` public API is stable and documented
☐ No floating dependencies (all git refs pinned)
☐ Self-test passes on all platforms
☐ Example app runs on all platforms
☐ No raw private keys exposed to Dart
``pubspec.yaml`` is publishable (or git-installable)
The LetUsMsg app will:
* Add this plugin via ``pubspec.yaml``
* Call ``CccCrypto.cccInit()`` at startup
* Replace existing crypto stubs with plugin calls
* Populate ``CccProviderCatalog`` from runtime capabilities
* Surface ``CccSelfTest.runAll()`` in debug UI
No Rust changes and no bridge changes are permitted during Milestone 3.
----

View File

@ -0,0 +1,127 @@
=====================================================
CCC Rust Milestone 2 — Session State (Planning)
=====================================================
:Status: Not started
:Date: 2026-02-26
:Repository target: ``ccc_cryptography`` (plugin repo)
:Depends on: ``ccc_rust`` Milestone 1 complete
Related Documents
=================
* Milestone 1 completion record:
``docs/ccc_rust_milestone1.rst``
Overview
========
This document tracks Milestone 2 execution state for Flutter plugin + bridge work.
Milestone 2 begins with Milestone 1 already verified and complete.
Current Gate Preconditions
==========================
* ``[x]`` Milestone 1 verification gate passed.
* ``[x]`` Conformance vectors passed in Rust workspace.
* ``[x]`` Rust target builds validated (iOS + Android).
Milestone 2 Work Checklist
==========================
Phase 1 — Repository + Scaffold
-------------------------------
* ``[ ]`` Create/confirm ``ccc_cryptography`` repository and branch strategy.
* ``[ ]`` Create Flutter plugin scaffold (``pubspec.yaml``, ``ios/``, ``android/``, ``macos/``).
* ``[ ]`` Add Rust bridge crate with ``crate-type = ["cdylib", "staticlib"]``.
* ``[ ]`` Wire dependency on ``ccc_rust`` pinned tag/revision.
Phase 2 — Bridge API Surface
----------------------------
* ``[ ]`` Define DTOs:
* ``CapabilitiesDto``
* ``KemKeyPairDto``
* ``KemEncapDto``
* ``SelfTestDto``
* ``AlgoTestResultDto``
* ``[ ]`` Implement bridge entry points:
* ``ccc_init``
* ``ccc_list_providers``
* ``ccc_capabilities`` / ``ccc_available_algorithms``
* ``ccc_aead_encrypt`` / ``ccc_aead_decrypt``
* ``ccc_kdf_derive``
* ``ccc_mac_compute`` / ``ccc_mac_verify``
* ``ccc_hash``
* ``ccc_kem_generate_keypair``
* ``ccc_kem_encapsulate`` / ``ccc_kem_decapsulate``
* ``ccc_self_test``
Phase 3 — FRB Codegen + Build Integration
-----------------------------------------
* ``[ ]`` Add ``flutter_rust_bridge`` configuration + codegen scripts.
* ``[ ]`` Run FRB codegen and commit generated artifacts.
* ``[ ]`` Verify plugin compiles for iOS.
* ``[ ]`` Verify plugin compiles for Android.
* ``[ ]`` Verify plugin compiles for macOS.
Phase 4 — Dart API Layer
------------------------
* ``[ ]`` Implement ``CccCrypto`` service API wrapper.
* ``[ ]`` Implement ``CccSelfTest`` wrapper.
* ``[ ]`` Implement runtime ``CccProviderCatalog`` population.
* ``[ ]`` Ensure algorithm ID mapping remains 1:1 with Rust discriminants.
Phase 5 — Integration + Validation
----------------------------------
* ``[ ]`` Add integration tests for AEAD roundtrip (at least AES-GCM and ChaCha20).
* ``[ ]`` Add integration tests for KEM keygen/encap/decap flow.
* ``[ ]`` Add integration tests for self-test API.
* ``[ ]`` Run on iOS simulator.
* ``[ ]`` Run on Android emulator/device.
Milestone 2 TODO Queue
======================
Immediate TODOs (next session)
------------------------------
* ``[ ]`` Decide exact Milestone 2 repository location/URL and baseline branch.
* ``[ ]`` Pin ``ccc_rust`` dependency to a reproducible reference (tag or commit hash).
* ``[ ]`` Define FRB module layout and generated file commit policy.
* ``[ ]`` Draft DTO type mapping table (Rust type -> bridge DTO -> Dart model).
Backlog TODOs
-------------
* ``[ ]`` Add CI job matrix for iOS/macOS/Android plugin builds.
* ``[ ]`` Add versioning/release policy for plugin package.
* ``[ ]`` Add troubleshooting notes for NDK/Xcode toolchains.
Milestone 2 Verification Gate
=============================
All of the following must pass before declaring Milestone 2 complete:
* ``[ ]`` FRB bridge API compiles and loads in Flutter plugin.
* ``[ ]`` Generated Dart bindings are committed and reproducible.
* ``[ ]`` ``flutter build ios`` succeeds.
* ``[ ]`` ``flutter build apk`` succeeds.
* ``[ ]`` ``flutter build macos`` succeeds.
* ``[ ]`` Integration test suite passes on iOS simulator.
* ``[ ]`` Integration test suite passes on Android emulator/device.
* ``[ ]`` Plugin package is tagged/released at ``v0.1.0`` (or agreed target version).
Notes
=====
* Milestone 2 is the first place where ``flutter_rust_bridge`` is allowed.
* Milestone 1 Rust workspace remains bridge-free and should not be modified
for Dart/plugin scaffolding.

387
docs/ccc_rust_plan.rst Normal file
View File

@ -0,0 +1,387 @@
===============================================
CCC Rust Crypto Provider — Architecture Plan
===============================================
:Status: Approved
:Date: 2026-02-24
:Author: Engineering
Overview
--------
This document describes the architecture for the **CCC Rust Crypto Provider**,
the first of three milestones in delivering hardware-grade cryptography to the
LetUsMsg application.
The guiding constraint is *clean separation*: each milestone is a distinct,
independently testable artifact with no forbidden upward dependencies.
----
Three-Milestone Strategy
------------------------
============= =================================== ========================== ===========================
Milestone Repository What ships Depends on
============= =================================== ========================== ===========================
**1 (this)** ``ccc_rust`` Pure Rust crypto library wolfSSL (vendored)
**2** ``ccc_dart_plugin`` Flutter plugin + Dart API ``ccc_rust`` (git/semver)
**3** ``letusmsg`` (existing app) App integration ``ccc_dart_plugin`` package
============= =================================== ========================== ===========================
Milestone 1 is complete and independently verified *before* any bridge or Dart
code is written. Milestone 2 owns the ``flutter_rust_bridge`` dependency and
all generated Dart bindings. Milestone 3 makes no Rust changes; it consumes
only the published Dart package.
----
Milestone 1 — ``ccc_rust`` Scope (this repository)
**Goal**: a fully tested, provider-agnostic Rust crypto library.
**Hard boundaries** — this repo must never contain:
* ``flutter_rust_bridge`` or any Flutter/Dart dependency
* Generated Dart files (``frb_generated.rs``, ``*.dart``)
* ``flutter_rust_bridge.yaml``
* Any platform plugin scaffold (``ios/``, ``android/``, ``macos/``)
Guiding Principles
~~~~~~~~~~~~~~~~~~
1. Every provider reports its own capabilities at runtime — no compile-time
hard-coding of ``available: true/false``.
2. Algorithm IDs in Rust map 1-to-1 to the integer constants in
``cipher_constants.dart`` — zero Dart changes needed when wiring up.
3. Key material is zeroed on drop (``zeroize`` crate) everywhere.
4. A conformance test suite validates NIST/RFC vectors for every algorithm
before any provider is marked ``available``.
5. The library has no runtime dependency on Flutter; it is consumable by any
FFI host (Flutter plugin, Python tests, CLI tools).
Repository Layout (Milestone 1 — this repo)
::
ccc_rust/
├── Cargo.toml ← workspace manifest (3 members, no bridge)
├── rust-toolchain.toml ← pinned stable toolchain
├── .cargo/
│ └── config.toml ← cross-compile target aliases
├── vendors/
│ ├── README.md ← submodule pin rationale + upgrade notes
│ └── wolfssl/ ← git submodule (wolfSSL/wolfssl @ v5.7.2-stable)
├── crates/
│ ├── ccc-crypto-core/ ← shared traits, enums, registry
│ │ ├── Cargo.toml
│ │ └── src/
│ │ ├── lib.rs
│ │ ├── algorithms.rs ← algorithm enums (values == cipher_constants.dart)
│ │ ├── capabilities.rs ← AlgorithmCapability, ProviderCapabilities
│ │ ├── error.rs ← CryptoError enum
│ │ ├── provider.rs ← CryptoProvider umbrella trait
│ │ ├── registry.rs ← ProviderRegistry (OnceLock<Mutex<...>>)
│ │ └── types.rs ← KemKeyPair, SelfTestReport, BenchmarkReport
│ └── ccc-crypto-wolfssl/ ← wolfSSL provider implementation
│ ├── Cargo.toml
│ └── src/
│ ├── lib.rs
│ ├── aead.rs ← AES-256-GCM, ChaCha20-Poly1305, XChaCha20-Poly1305
│ ├── kdf.rs ← HKDF-SHA256/384/512, Argon2id, BLAKE2b-KDF
│ ├── mac.rs ← HMAC-SHA256/384/512, BLAKE2b-MAC
│ ├── hash.rs ← SHA-256/384/512, SHA3-256/512, BLAKE2b-512
│ ├── kem.rs ← X25519, X448 (ML-KEM deferred Phase 5)
│ ├── capabilities.rs ← probe-at-startup + benchmark()
│ └── provider.rs ← WolfSslProvider: CryptoProvider impl
└── tests/
└── conformance/
├── Cargo.toml
└── src/
└── main.rs ← NIST/RFC vectors for all algorithms
Step 1 — Cargo Workspace Scaffold
``Cargo.toml``::
[workspace]
resolver = "2"
members = [
"crates/ccc-crypto-core",
"crates/ccc-crypto-wolfssl",
"tests/conformance",
]
``rust-toolchain.toml``::
[toolchain]
channel = "stable"
``.cargo/config.toml``::
[alias]
build-ios = "build --target aarch64-apple-ios"
build-android-arm64 = "build --target aarch64-linux-android"
build-android-x64 = "build --target x86_64-linux-android"
build-macos = "build --target aarch64-apple-darwin"
Step 2 — ``ccc-crypto-core`` Trait Crate
Algorithm Enumerations
~~~~~~~~~~~~~~~~~~~~~~
All discriminant values match the integer constants in ``cipher_constants.dart``
exactly, so the Dart cipher-sequencing logic requires zero changes.
=================== =========================================================
Enum Variants → value
=================== =========================================================
``AeadAlgorithm`` AesGcm256=12, ChaCha20Poly1305=13, XChaCha20Poly1305=14,
Ascon128a=15
``KdfAlgorithm`` Sha256=1, Sha384=2, Sha512=3, Blake2b512=4
``MacAlgorithm`` HmacSha256=30, HmacSha512=32, Blake2bMac=33
``HashAlgorithm`` Sha256=40, Sha384=41, Sha512=42, Blake2b512=43, Sha3_256=44
``KemAlgorithm`` X25519=50, X448=51, MlKem768=52, MlKem1024=53,
ClassicMcEliece=54
=================== =========================================================
Key Structs
~~~~~~~~~~~
``AlgorithmCapability``::
available: bool
deterministic_io: bool
efficiency_score: u8 // populated by WolfSslProvider::benchmark()
reliability_score: u8 // populated by WolfSslProvider::self_test()
``ProviderCapabilities``::
provider_name: &'static str
aead: HashMap<AeadAlgorithm, AlgorithmCapability>
kdf: HashMap<KdfAlgorithm, AlgorithmCapability>
mac: HashMap<MacAlgorithm, AlgorithmCapability>
hash: HashMap<HashAlgorithm, AlgorithmCapability>
kem: HashMap<KemAlgorithm, AlgorithmCapability>
``KemKeyPair``::
public_key: Zeroizing<Vec<u8>>
private_key: Zeroizing<Vec<u8>>
``CryptoError``::
UnsupportedAlgorithm(String)
InvalidKey(String)
InvalidNonce(String)
AuthenticationFailed
InternalError(String)
Provider Traits
~~~~~~~~~~~~~~~
.. code-block:: rust
pub trait AeadProvider {
fn encrypt_aead(
&self, algo: AeadAlgorithm,
key: &[u8], nonce: &[u8],
plaintext: &[u8], aad: &[u8],
) -> Result<Vec<u8>, CryptoError>;
fn decrypt_aead(
&self, algo: AeadAlgorithm,
key: &[u8], nonce: &[u8],
ciphertext: &[u8], aad: &[u8],
) -> Result<Vec<u8>, CryptoError>;
}
pub trait KdfProvider {
fn derive_key(
&self, algo: KdfAlgorithm,
ikm: &[u8], salt: &[u8], info: &[u8], length: usize,
) -> Result<Zeroizing<Vec<u8>>, CryptoError>;
}
pub trait MacProvider {
fn compute_mac(
&self, algo: MacAlgorithm, key: &[u8], data: &[u8],
) -> Result<Vec<u8>, CryptoError>;
fn verify_mac(
&self, algo: MacAlgorithm, key: &[u8],
data: &[u8], mac: &[u8],
) -> Result<bool, CryptoError>;
}
pub trait HashProvider {
fn hash(
&self, algo: HashAlgorithm, data: &[u8],
) -> Result<Vec<u8>, CryptoError>;
}
pub trait KemProvider {
fn generate_keypair(
&self, algo: KemAlgorithm,
) -> Result<KemKeyPair, CryptoError>;
fn encapsulate(
&self, algo: KemAlgorithm, public_key: &[u8],
) -> Result<(Vec<u8>, Zeroizing<Vec<u8>>), CryptoError>;
fn decapsulate(
&self, algo: KemAlgorithm,
private_key: &[u8], ciphertext: &[u8],
) -> Result<Zeroizing<Vec<u8>>, CryptoError>;
}
pub trait CryptoProvider:
AeadProvider + KdfProvider + MacProvider + HashProvider + Send + Sync
{
fn provider_name(&self) -> &'static str;
fn capabilities(&self) -> ProviderCapabilities;
fn self_test(&self) -> SelfTestReport;
fn benchmark(&self) -> BenchmarkReport;
}
``ProviderRegistry``::
OnceLock<Mutex<HashMap<&'static str, Box<dyn CryptoProvider + Send + Sync>>>>
fn register(name, provider)
fn get(name) -> Option<Arc<dyn CryptoProvider>>
fn list() -> Vec<&'static str>
Step 3 — wolfSSL Submodule + ``ccc-crypto-wolfssl``
wolfSSL is vendored as a git submodule pinned to ``v5.7.2-stable``.
The crate uses ``cmake`` + ``bindgen`` in ``build.rs`` to build and bind it.
A ``stub_ffi`` feature bypasses the C build for fast unit-test cycles.
wolfSSL Phase 4 Algorithm Coverage
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
=================== ===========================================
Category Algorithms
=================== ===========================================
AEAD AES-256-GCM, ChaCha20-Poly1305,
XChaCha20-Poly1305
KDF HKDF-SHA256/384/512, Argon2id, BLAKE2b-KDF
MAC HMAC-SHA256/384/512, BLAKE2b-MAC
Hash SHA-256/384/512, SHA3-256/512, BLAKE2b-512
KEM X25519, X448
KEM (Phase 5) ML-KEM-768, ML-KEM-1024, Classic McEliece
=================== ===========================================
Capability Probe Strategy
~~~~~~~~~~~~~~~~~~~~~~~~~~
``WolfSslProvider::capabilities()`` runs a minimal probe call (encrypt 1 byte;
decrypt; compare) per algorithm at startup. Sets ``available = probe_succeeded``.
If the wolfSSL build omits PQ support, ML-KEM entries report
``available: false`` gracefully.
Benchmark Strategy
~~~~~~~~~~~~~~~~~~
``WolfSslProvider::benchmark()`` encrypts a 1 MB buffer × 100 iterations per
AEAD algorithm, measures wall-clock throughput, normalises to a 0100
``efficiency_score``. Run once at library init and cached.
Step 4 — Conformance Test Suite
Location: ``tests/conformance/src/main.rs``
Run with ``cargo run -p ccc-conformance-tests`` and ``cargo test --workspace``.
========================= ================================
Test Source
========================= ================================
AES-256-GCM NIST SP 800-38D vectors
ChaCha20-Poly1305 RFC 8439 vectors
XChaCha20-Poly1305 Extended nonce vectors
HKDF-SHA256/512 RFC 5869 vectors
HMAC-SHA256/512 RFC 4231 vectors
SHA-256/512, SHA3, BLAKE2b FIPS / reference vectors
X25519 DH RFC 7748 vectors
X448 DH RFC 7748 vectors
========================= ================================
**Gate**: ``ALL VECTORS PASSED`` must print before Milestone 1 is tagged.
Step 5 — Architecture Documentation
``docs/ccc_rust_milestone1.rst`` covers:
* Crate dependency graph (ASCII)
* "How to add a new provider" — 7-step trait checklist
* ``algo: u32`` → cipher constant mapping table
* Milestone 2 hand-off contract (API surface Milestone 2 must implement against)
Milestone 1 Verification Gate
All of the following must pass before the ``v0.1.0`` tag is cut and Milestone 2
work begins:
* ``cargo test --workspace`` — all unit tests pass
* ``cargo run -p ccc-conformance-tests````ALL VECTORS PASSED``
* ``cargo build --target aarch64-apple-ios`` — compiles
* ``cargo build --target aarch64-linux-android`` — compiles
* No ``flutter_rust_bridge``, Dart, or Flutter dependency anywhere in the workspace
* ``cargo audit`` — no known CVEs in dependency tree
Milestone 2 — ``ccc_dart_plugin`` (separate repository)
*(Planned — not started. Work begins after Milestone 1 gate passes.)*
A separate Dart/Flutter plugin package repository. It contains:
* A small Rust bridge crate that references ``ccc_rust`` via git tag:
.. code-block:: toml
[dependencies]
ccc-crypto-core = { git = "https://github.com/letusmsg/ccc_rust", tag = "v0.1.0" }
ccc-crypto-wolfssl = { git = "https://github.com/letusmsg/ccc_rust", tag = "v0.1.0" }
flutter_rust_bridge = "2"
* ``flutter_rust_bridge_codegen generate`` output (``frb_generated.rs``, Dart bindings)
* Flutter plugin scaffold: ``ios/``, ``android/``, ``macos/``
* Dart API surface: ``CccCrypto``, ``CccSelfTest``, ``CccProviderCatalog``
* Flutter integration tests (roundtrip encrypt/decrypt, self-test harness)
Milestone 3 — LetUsMsg App Integration (existing repository)
*(Planned — not started. Work begins after Milestone 2 gate passes.)*
The existing ``letusmsg`` Flutter app adds ``ccc_dart_plugin`` as a pubspec
dependency. Changes are confined to:
* ``crypto_wolfssl.dart`` — replace ``UnimplementedError`` stubs with plugin calls
* ``ccc_provider_spec.dart`` — populate ``CccProviderCatalog`` at runtime
* ``main.dart`` — call ``CccCrypto.cccInit()`` at startup
* App debug screen — expose ``CccSelfTest.runAll()`` results
No Rust changes and no bridge changes are made in Milestone 3.
Phase 8 — Stretch Goal Providers (Future)
*(Out of scope for Phase 4. Tracked here for future scheduling.)*
================== =====================================================
Library Rust crate / approach
================== =====================================================
libsodium ``sodiumoxide`` or ``safe_libsodium``
OpenSSL ``openssl`` crate
BoringSSL ``boring`` crate
RustCrypto Pure-Rust trait impls; no native dep
liboqs Open Quantum Safe — ML-KEM, BIKE, HQC, Falcon,
Dilithium, SPHINCS+
Signal libsignal ``libsignal`` (Apache-2 subset)
Botan ``botan`` crate
mbedTLS ``mbedtls`` crate
Nettle ``nettle-sys`` crate
================== =====================================================

View File

@ -0,0 +1,264 @@
==============================================
CCC Rust Implementation — Phase Tracking
==============================================
:Last Updated: 2026-02-25
Legend
------
* ``[ ]`` Not started
* ``[~]`` In progress
* ``[x]`` Complete
* ``[!]`` Blocked
----
Three-Milestone Overview
------------------------
============= =================================== ============================
Milestone Repository Status
============= =================================== ============================
**1 (this)** ``ccc_rust`` Complete
**2** ``ccc_cryptography`` Not started
**3** ``letusmsg`` (existing app) Not started
============= =================================== ============================
Milestone 1 Verification Gate is now passing.
Milestone 2 may begin when scheduled.
Milestone 3 does not start until the Milestone 2 gate passes.
----
============================================================
Milestone 1 — ``ccc_rust`` Pure Rust Crypto Library
============================================================
Phase 1 — Cargo Workspace Scaffold
----------------------------------
* ``[x]`` Create ``Cargo.toml`` (workspace manifest, 3 members — no bridge crate)
* ``[x]`` Create ``rust-toolchain.toml`` (channel = "stable")
* ``[x]`` Create ``.cargo/config.toml`` (cross-compile target aliases)
* ``[x]`` Create ``vendors/README.md``
----
Phase 2 — ``ccc-crypto-core`` Trait Crate
-----------------------------------------
* ``[x]`` Create ``crates/ccc-crypto-core/Cargo.toml``
* ``[x]`` ``algorithms.rs`` — AeadAlgorithm, KdfAlgorithm, MacAlgorithm,
HashAlgorithm, KemAlgorithm enums (values == cipher_constants.dart)
* ``[x]`` ``capabilities.rs`` — AlgorithmCapability, ProviderCapabilities
* ``[x]`` ``error.rs`` — CryptoError enum
* ``[x]`` ``types.rs`` — KemKeyPair, SelfTestReport, BenchmarkReport,
AlgoTestResult
* ``[x]`` ``provider.rs`` — AeadProvider, KdfProvider, MacProvider,
HashProvider, KemProvider traits; CryptoProvider umbrella trait
* ``[x]`` ``registry.rs`` — ProviderRegistry (OnceLock<Mutex<...>>),
register(), get(), list()
* ``[x]`` ``lib.rs`` — re-exports all public items
* ``[x]`` Unit tests for registry (5 passing)
----
Phase 3 — wolfSSL Submodule + ``ccc-crypto-wolfssl``
-----------------------------------------------------
* ``[x]`` ``git submodule add`` wolfSSL → ``vendors/wolfssl``
* ``[x]`` Pin submodule to ``v5.7.2-stable``
* ``[x]`` Document pin in ``vendors/README.md``
* ``[x]`` Create ``crates/ccc-crypto-wolfssl/Cargo.toml``
* ``[x]`` ``build.rs`` — cmake build + bindgen; stub_ffi feature bypasses C build
* ``[x]`` ``aead.rs`` — AES-256-GCM implementation
* ``[x]`` encrypt_aead (AES-256-GCM)
* ``[x]`` decrypt_aead (AES-256-GCM)
* ``[x]`` encrypt_aead (ChaCha20-Poly1305)
* ``[x]`` decrypt_aead (ChaCha20-Poly1305)
* ``[x]`` encrypt_aead (XChaCha20-Poly1305 via HChaCha20)
* ``[x]`` decrypt_aead (XChaCha20-Poly1305)
* ``[x]`` ``kdf.rs`` — KDF implementations
* ``[x]`` HKDF-SHA256
* ``[x]`` HKDF-SHA384
* ``[x]`` HKDF-SHA512
* ``[x]`` Argon2id (64 MB / 3 iter / 4 threads — matches DEFAULT_CIPHER_PARAMS)
* ``[x]`` BLAKE2b-512 KDF
* ``[x]`` ``mac.rs`` — MAC implementations
* ``[x]`` HMAC-SHA256
* ``[x]`` HMAC-SHA384
* ``[x]`` HMAC-SHA512
* ``[x]`` BLAKE2b-MAC (keyed)
* ``[x]`` Constant-time verify
* ``[x]`` ``hash.rs`` — Hash implementations
* ``[x]`` SHA-256 / SHA-384 / SHA-512
* ``[x]`` SHA3-256 / SHA3-512
* ``[x]`` BLAKE2b-512
* ``[x]`` ``kem.rs`` — KEM implementations
* ``[x]`` X25519 (keygen + DH encap/decap)
* ``[x]`` X448 (keygen + DH encap/decap)
* ``[ ]`` ML-KEM-768 (deferred to Phase 5)
* ``[ ]`` ML-KEM-1024 (deferred to Phase 5)
* ``[ ]`` Classic McEliece (deferred to Phase 5)
* ``[x]`` ``capabilities.rs`` — probe-at-startup per algorithm
* ``[x]`` ``capabilities.rs`` — benchmark() throughput micro-bench
* ``[x]`` ``provider.rs`` — WolfSslProvider: CryptoProvider impl
* ``[x]`` ``provider.rs`` — self_test() with embedded NIST vectors (AES-256-GCM, ChaCha20-Poly1305)
* ``[x]`` Register WolfSslProvider in ProviderRegistry via init()
* ``[x]`` Full native build verified (cmake builds clean, all conformance tests pass)
----
Phase 4 — Conformance Test Suite
---------------------------------
* ``[x]`` NIST AES-256-GCM vectors (2 vectors)
* ``[x]`` RFC 8439 ChaCha20-Poly1305 vectors
* ``[x]`` RFC 5869 HKDF-SHA256 vectors (2 vectors)
* ``[x]`` RFC 4231 HMAC-SHA256 vectors (2 vectors)
* ``[x]`` FIPS hash vectors (SHA-256/512, SHA3-256, BLAKE2b-512)
* ``[x]`` RFC 7748 X25519 DH test vectors
* ``[x]`` RFC 7748 X448 DH test vectors
* ``[x]`` XChaCha20-Poly1305 extended-nonce vectors
* ``[x]`` ``cargo run -p ccc-conformance-tests`` passes (all current vectors)
----
Phase 5 — Architecture Documentation
--------------------------------------
* ``[x]`` Create ``docs/ccc_rust_milestone1.rst``
* ``[x]`` Crate dependency graph (ASCII diagram)
* ``[x]`` "How to add a new provider" — 7-step trait checklist
* ``[x]`` ``algo: u32`` → cipher constant mapping table
* ``[x]`` Milestone 2 hand-off contract documented
----
Milestone 1 Verification Gate
------------------------------
*All items must be checked before the* ``v0.1.0`` *tag is cut.*
* ``[x]`` ``cargo test --workspace`` — all pass
* ``[x]`` ``cargo run -p ccc-conformance-tests`` — ALL VECTORS PASSED
* ``[x]`` ``cargo build --target aarch64-apple-ios`` — success
* ``[x]`` ``cargo build --target aarch64-linux-android`` — success
* ``[x]`` No ``flutter_rust_bridge`` / Dart / Flutter dependency in workspace
* ``[x]`` ``cargo audit`` — no known CVEs
----
============================================================
Milestone 2 — ``ccc_cryptography`` Flutter Plugin
===========================================================
*(Not started — begins after Milestone 1 gate passes)*
Phase 1 — New Repository Setup
-------------------------------
* ``[ ]`` Create ``ccc_cryptography`` repository
* ``[ ]`` Flutter plugin scaffold (``pubspec.yaml``, ``ios/``, ``android/``, ``macos/``)
* ``[ ]`` Rust bridge crate with ``crate-type = ["cdylib", "staticlib"]``
* ``[ ]`` Add ``flutter_rust_bridge = "2"`` dependency
* ``[ ]`` Reference ``ccc_rust`` via git tag ``v0.1.0``
----
Phase 2 — Bridge Crate
----------------------
* ``[ ]`` ``dto.rs`` — CapabilitiesDto, KemKeyPairDto, KemEncapDto,
SelfTestDto, AlgoTestResultDto; From<core types> impls
* ``[ ]`` ``bridge.rs`` — ccc_init()
* ``[ ]`` ``bridge.rs`` — ccc_list_providers()
* ``[ ]`` ``bridge.rs`` — ccc_capabilities() / ccc_available_algorithms()
* ``[ ]`` ``bridge.rs`` — ccc_aead_encrypt() / ccc_aead_decrypt()
* ``[ ]`` ``bridge.rs`` — ccc_kdf_derive()
* ``[ ]`` ``bridge.rs`` — ccc_mac_compute() / ccc_mac_verify()
* ``[ ]`` ``bridge.rs`` — ccc_hash()
* ``[ ]`` ``bridge.rs`` — ccc_kem_generate_keypair()
* ``[ ]`` ``bridge.rs`` — ccc_kem_encapsulate() / ccc_kem_decapsulate()
* ``[ ]`` ``bridge.rs`` — ccc_self_test()
----
Phase 3 — Codegen + Plugin Build
---------------------------------
* ``[ ]`` Run ``flutter_rust_bridge_codegen generate``
* ``[ ]`` Verify generated Dart bindings compile
* ``[ ]`` ``flutter build ios`` succeeds (static lib linked)
* ``[ ]`` ``flutter build apk`` succeeds (cdylib linked)
* ``[ ]`` ``flutter build macos`` succeeds
----
Phase 4 — Dart API Layer
------------------------
* ``[ ]`` ``CccCrypto`` class (wraps all bridge calls)
* ``[ ]`` ``CccSelfTest`` class (wraps ccc_self_test())
* ``[ ]`` ``CccProviderCatalog`` (runtime-populated from ccc_capabilities())
----
Phase 5 — Flutter Integration Tests
------------------------------------
* ``[ ]`` Roundtrip encrypt/decrypt 1 KB (AES-256-GCM)
* ``[ ]`` Roundtrip encrypt/decrypt 1 KB (ChaCha20-Poly1305)
* ``[ ]`` ``CccSelfTest.runAll()`` — all-pass
----
Milestone 2 Verification Gate
------------------------------
* ``[ ]`` All Flutter integration tests pass on iOS simulator
* ``[ ]`` All Flutter integration tests pass on Android emulator
* ``[ ]`` Package published / tagged ``v0.1.0``
----
============================================================
Milestone 3 — LetUsMsg App Integration
============================================================
*(Not started — begins after Milestone 2 gate passes)*
* ``[ ]`` Add ``ccc_cryptography`` to ``letusmsg`` `pubspec.yaml``
* ``[ ]`` Wire ``crypto_wolfssl.dart`` encrypt/decrypt → bridge calls
* ``[ ]`` Call ``CccCrypto.cccInit()`` at app startup
* ``[ ]`` Populate ``CccProviderCatalog`` from runtime capabilities
* ``[ ]`` Expose ``CccSelfTest.runAll()`` in app debug screen
* ``[ ]`` End-to-end integration test (send + receive encrypted message)
----
Phase 8 — Stretch Goal Providers (Future)
------------------------------------------
*(Out of scope for Phase 4. Tracked here for future scheduling.)*
* ``[ ]`` libsodium (``sodiumoxide`` / ``safe_libsodium``)
* ``[ ]`` OpenSSL (``openssl`` crate)
* ``[ ]`` BoringSSL (``boring`` crate)
* ``[ ]`` RustCrypto (pure-Rust, no native dep)
* ``[ ]`` liboqs — ML-KEM, BIKE, HQC, Falcon, Dilithium, SPHINCS+
* ``[ ]`` Signal ``libsignal``
* ``[ ]`` Botan
* ``[ ]`` mbedTLS
* ``[ ]`` Nettle

View File

@ -0,0 +1,11 @@
import 'package:integration_test/integration_test.dart';
import 'package:flutter_test/flutter_test.dart';
import 'package:ccc_cryptography/ccc_cryptography.dart';
void main() {
IntegrationTestWidgetsFlutterBinding.ensureInitialized();
setUpAll(() async => await RustLib.init());
test('Can call rust function', () async {
expect(greet(name: "Tom"), "Hello, Tom!");
});
}

View File

@ -1 +1,2 @@
#include? "Pods/Target Support Files/Pods-Runner/Pods-Runner.debug.xcconfig"
#include "Generated.xcconfig"

View File

@ -1 +1,2 @@
#include? "Pods/Target Support Files/Pods-Runner/Pods-Runner.release.xcconfig"
#include "Generated.xcconfig"

43
example/ios/Podfile Normal file
View File

@ -0,0 +1,43 @@
# Uncomment this line to define a global platform for your project
# platform :ios, '13.0'
# CocoaPods analytics sends network stats synchronously affecting flutter build latency.
ENV['COCOAPODS_DISABLE_STATS'] = 'true'
project 'Runner', {
'Debug' => :debug,
'Profile' => :release,
'Release' => :release,
}
def flutter_root
generated_xcode_build_settings_path = File.expand_path(File.join('..', 'Flutter', 'Generated.xcconfig'), __FILE__)
unless File.exist?(generated_xcode_build_settings_path)
raise "#{generated_xcode_build_settings_path} must exist. If you're running pod install manually, make sure flutter pub get is executed first"
end
File.foreach(generated_xcode_build_settings_path) do |line|
matches = line.match(/FLUTTER_ROOT\=(.*)/)
return matches[1].strip if matches
end
raise "FLUTTER_ROOT not found in #{generated_xcode_build_settings_path}. Try deleting Generated.xcconfig, then run flutter pub get"
end
require File.expand_path(File.join('packages', 'flutter_tools', 'bin', 'podhelper'), flutter_root)
flutter_ios_podfile_setup
target 'Runner' do
use_frameworks!
flutter_install_all_ios_pods File.dirname(File.realpath(__FILE__))
target 'RunnerTests' do
inherit! :search_paths
end
end
post_install do |installer|
installer.pods_project.targets.each do |target|
flutter_additional_ios_build_settings(target)
end
end

View File

@ -1,9 +1,9 @@
import 'package:flutter/material.dart';
import 'dart:async';
import 'package:ccc_cryptography/src/rust/api/simple.dart';
import 'package:ccc_cryptography/src/rust/frb_generated.dart';
import 'package:ccc_cryptography/ccc_cryptography.dart' as ccc_cryptography;
void main() {
Future<void> main() async {
await RustLib.init();
runApp(const MyApp());
}
@ -15,57 +15,25 @@ class MyApp extends StatefulWidget {
}
class _MyAppState extends State<MyApp> {
late int sumResult;
late Future<int> sumAsyncResult;
late String greetResult;
@override
void initState() {
super.initState();
sumResult = ccc_cryptography.sum(1, 2);
sumAsyncResult = ccc_cryptography.sumAsync(3, 4);
greetResult = greet(name: 'Flutter');
}
@override
Widget build(BuildContext context) {
const textStyle = TextStyle(fontSize: 25);
const spacerSmall = SizedBox(height: 10);
return MaterialApp(
home: Scaffold(
appBar: AppBar(
title: const Text('Native Packages'),
),
body: SingleChildScrollView(
child: Container(
padding: const .all(10),
child: Column(
children: [
const Text(
'This calls a native function through FFI that is shipped as source in the package. '
'The native code is built as part of the Flutter Runner build.',
style: textStyle,
textAlign: .center,
),
spacerSmall,
Text(
'sum(1, 2) = $sumResult',
style: textStyle,
textAlign: .center,
),
spacerSmall,
FutureBuilder<int>(
future: sumAsyncResult,
builder: (BuildContext context, AsyncSnapshot<int> value) {
final displayValue =
(value.hasData) ? value.data : 'loading';
return Text(
'await sumAsync(3, 4) = $displayValue',
style: textStyle,
textAlign: .center,
);
},
),
],
),
appBar: AppBar(title: const Text('ccc_cryptography')),
body: Center(
child: Text(
greetResult,
style: textStyle,
textAlign: TextAlign.center,
),
),
),

View File

@ -1 +1,2 @@
#include? "Pods/Target Support Files/Pods-Runner/Pods-Runner.debug.xcconfig"
#include "ephemeral/Flutter-Generated.xcconfig"

View File

@ -1 +1,2 @@
#include? "Pods/Target Support Files/Pods-Runner/Pods-Runner.release.xcconfig"
#include "ephemeral/Flutter-Generated.xcconfig"

42
example/macos/Podfile Normal file
View File

@ -0,0 +1,42 @@
platform :osx, '10.15'
# CocoaPods analytics sends network stats synchronously affecting flutter build latency.
ENV['COCOAPODS_DISABLE_STATS'] = 'true'
project 'Runner', {
'Debug' => :debug,
'Profile' => :release,
'Release' => :release,
}
def flutter_root
generated_xcode_build_settings_path = File.expand_path(File.join('..', 'Flutter', 'ephemeral', 'Flutter-Generated.xcconfig'), __FILE__)
unless File.exist?(generated_xcode_build_settings_path)
raise "#{generated_xcode_build_settings_path} must exist. If you're running pod install manually, make sure \"flutter pub get\" is executed first"
end
File.foreach(generated_xcode_build_settings_path) do |line|
matches = line.match(/FLUTTER_ROOT\=(.*)/)
return matches[1].strip if matches
end
raise "FLUTTER_ROOT not found in #{generated_xcode_build_settings_path}. Try deleting Flutter-Generated.xcconfig, then run \"flutter pub get\""
end
require File.expand_path(File.join('packages', 'flutter_tools', 'bin', 'podhelper'), flutter_root)
flutter_macos_podfile_setup
target 'Runner' do
use_frameworks!
flutter_install_all_macos_pods File.dirname(File.realpath(__FILE__))
target 'RunnerTests' do
inherit! :search_paths
end
end
post_install do |installer|
installer.pods_project.targets.each do |target|
flutter_additional_macos_build_settings(target)
end
end

View File

@ -27,6 +27,8 @@
33CC10F32044A3C60003C045 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 33CC10F22044A3C60003C045 /* Assets.xcassets */; };
33CC10F62044A3C60003C045 /* MainMenu.xib in Resources */ = {isa = PBXBuildFile; fileRef = 33CC10F42044A3C60003C045 /* MainMenu.xib */; };
33CC11132044BFA00003C045 /* MainFlutterWindow.swift in Sources */ = {isa = PBXBuildFile; fileRef = 33CC11122044BFA00003C045 /* MainFlutterWindow.swift */; };
C9D9D80953306779817A01D7 /* Pods_Runner.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 038972E62E6D13C2A55A0B7F /* Pods_Runner.framework */; };
CC6FDE117C14C0F98D1BA8BB /* Pods_RunnerTests.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = D5AA6C665A590100A722C2D2 /* Pods_RunnerTests.framework */; };
/* End PBXBuildFile section */
/* Begin PBXContainerItemProxy section */
@ -60,11 +62,13 @@
/* End PBXCopyFilesBuildPhase section */
/* Begin PBXFileReference section */
038972E62E6D13C2A55A0B7F /* Pods_Runner.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_Runner.framework; sourceTree = BUILT_PRODUCTS_DIR; };
0988C826A2FD255462F9808A /* Pods-Runner.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.debug.xcconfig"; path = "Target Support Files/Pods-Runner/Pods-Runner.debug.xcconfig"; sourceTree = "<group>"; };
331C80D5294CF71000263BE5 /* RunnerTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = RunnerTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; };
331C80D7294CF71000263BE5 /* RunnerTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RunnerTests.swift; sourceTree = "<group>"; };
333000ED22D3DE5D00554162 /* Warnings.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = Warnings.xcconfig; sourceTree = "<group>"; };
335BBD1A22A9A15E00E9071D /* GeneratedPluginRegistrant.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = GeneratedPluginRegistrant.swift; sourceTree = "<group>"; };
33CC10ED2044A3C60003C045 /* ccc_cryptography_example.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = "ccc_cryptography_example.app"; sourceTree = BUILT_PRODUCTS_DIR; };
33CC10ED2044A3C60003C045 /* ccc_cryptography_example.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = ccc_cryptography_example.app; sourceTree = BUILT_PRODUCTS_DIR; };
33CC10F02044A3C60003C045 /* AppDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = "<group>"; };
33CC10F22044A3C60003C045 /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; name = Assets.xcassets; path = Runner/Assets.xcassets; sourceTree = "<group>"; };
33CC10F52044A3C60003C045 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = Base; path = Base.lproj/MainMenu.xib; sourceTree = "<group>"; };
@ -77,7 +81,13 @@
33E51914231749380026EE4D /* Release.entitlements */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.entitlements; path = Release.entitlements; sourceTree = "<group>"; };
33E5194F232828860026EE4D /* AppInfo.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = AppInfo.xcconfig; sourceTree = "<group>"; };
7AFA3C8E1D35360C0083082E /* Release.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = Release.xcconfig; sourceTree = "<group>"; };
86D70DA30699567E710A0459 /* Pods-Runner.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.release.xcconfig"; path = "Target Support Files/Pods-Runner/Pods-Runner.release.xcconfig"; sourceTree = "<group>"; };
9740EEB21CF90195004384FC /* Debug.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; path = Debug.xcconfig; sourceTree = "<group>"; };
9D35F14235952B671983F7E0 /* Pods-RunnerTests.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-RunnerTests.release.xcconfig"; path = "Target Support Files/Pods-RunnerTests/Pods-RunnerTests.release.xcconfig"; sourceTree = "<group>"; };
A5B81D3E19756CB2D0C8B009 /* Pods-RunnerTests.profile.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-RunnerTests.profile.xcconfig"; path = "Target Support Files/Pods-RunnerTests/Pods-RunnerTests.profile.xcconfig"; sourceTree = "<group>"; };
A81A44EB7B90A16EAADE4FA6 /* Pods-RunnerTests.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-RunnerTests.debug.xcconfig"; path = "Target Support Files/Pods-RunnerTests/Pods-RunnerTests.debug.xcconfig"; sourceTree = "<group>"; };
BA626D8003BA6E48536EE306 /* Pods-Runner.profile.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.profile.xcconfig"; path = "Target Support Files/Pods-Runner/Pods-Runner.profile.xcconfig"; sourceTree = "<group>"; };
D5AA6C665A590100A722C2D2 /* Pods_RunnerTests.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_RunnerTests.framework; sourceTree = BUILT_PRODUCTS_DIR; };
/* End PBXFileReference section */
/* Begin PBXFrameworksBuildPhase section */
@ -85,6 +95,7 @@
isa = PBXFrameworksBuildPhase;
buildActionMask = 2147483647;
files = (
CC6FDE117C14C0F98D1BA8BB /* Pods_RunnerTests.framework in Frameworks */,
);
runOnlyForDeploymentPostprocessing = 0;
};
@ -92,6 +103,7 @@
isa = PBXFrameworksBuildPhase;
buildActionMask = 2147483647;
files = (
C9D9D80953306779817A01D7 /* Pods_Runner.framework in Frameworks */,
);
runOnlyForDeploymentPostprocessing = 0;
};
@ -125,6 +137,7 @@
331C80D6294CF71000263BE5 /* RunnerTests */,
33CC10EE2044A3C60003C045 /* Products */,
D73912EC22F37F3D000D13A0 /* Frameworks */,
DE0D4D416823266B5CAAEDA7 /* Pods */,
);
sourceTree = "<group>";
};
@ -175,10 +188,26 @@
D73912EC22F37F3D000D13A0 /* Frameworks */ = {
isa = PBXGroup;
children = (
038972E62E6D13C2A55A0B7F /* Pods_Runner.framework */,
D5AA6C665A590100A722C2D2 /* Pods_RunnerTests.framework */,
);
name = Frameworks;
sourceTree = "<group>";
};
DE0D4D416823266B5CAAEDA7 /* Pods */ = {
isa = PBXGroup;
children = (
0988C826A2FD255462F9808A /* Pods-Runner.debug.xcconfig */,
86D70DA30699567E710A0459 /* Pods-Runner.release.xcconfig */,
BA626D8003BA6E48536EE306 /* Pods-Runner.profile.xcconfig */,
A81A44EB7B90A16EAADE4FA6 /* Pods-RunnerTests.debug.xcconfig */,
9D35F14235952B671983F7E0 /* Pods-RunnerTests.release.xcconfig */,
A5B81D3E19756CB2D0C8B009 /* Pods-RunnerTests.profile.xcconfig */,
);
name = Pods;
path = Pods;
sourceTree = "<group>";
};
/* End PBXGroup section */
/* Begin PBXNativeTarget section */
@ -186,6 +215,7 @@
isa = PBXNativeTarget;
buildConfigurationList = 331C80DE294CF71000263BE5 /* Build configuration list for PBXNativeTarget "RunnerTests" */;
buildPhases = (
086D907707E0A9BB81BA038A /* [CP] Check Pods Manifest.lock */,
331C80D1294CF70F00263BE5 /* Sources */,
331C80D2294CF70F00263BE5 /* Frameworks */,
331C80D3294CF70F00263BE5 /* Resources */,
@ -204,11 +234,13 @@
isa = PBXNativeTarget;
buildConfigurationList = 33CC10FB2044A3C60003C045 /* Build configuration list for PBXNativeTarget "Runner" */;
buildPhases = (
C86250B37FA1453AAEC9A1C2 /* [CP] Check Pods Manifest.lock */,
33CC10E92044A3C60003C045 /* Sources */,
33CC10EA2044A3C60003C045 /* Frameworks */,
33CC10EB2044A3C60003C045 /* Resources */,
33CC110E2044A8840003C045 /* Bundle Framework */,
3399D490228B24CF009A79C7 /* ShellScript */,
78F7E7C7FE2E75BBB3819847 /* [CP] Embed Pods Frameworks */,
);
buildRules = (
);
@ -291,6 +323,28 @@
/* End PBXResourcesBuildPhase section */
/* Begin PBXShellScriptBuildPhase section */
086D907707E0A9BB81BA038A /* [CP] Check Pods Manifest.lock */ = {
isa = PBXShellScriptBuildPhase;
buildActionMask = 2147483647;
files = (
);
inputFileListPaths = (
);
inputPaths = (
"${PODS_PODFILE_DIR_PATH}/Podfile.lock",
"${PODS_ROOT}/Manifest.lock",
);
name = "[CP] Check Pods Manifest.lock";
outputFileListPaths = (
);
outputPaths = (
"$(DERIVED_FILE_DIR)/Pods-RunnerTests-checkManifestLockResult.txt",
);
runOnlyForDeploymentPostprocessing = 0;
shellPath = /bin/sh;
shellScript = "diff \"${PODS_PODFILE_DIR_PATH}/Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n# This output is used by Xcode 'outputs' to avoid re-running this script phase.\necho \"SUCCESS\" > \"${SCRIPT_OUTPUT_FILE_0}\"\n";
showEnvVarsInLog = 0;
};
3399D490228B24CF009A79C7 /* ShellScript */ = {
isa = PBXShellScriptBuildPhase;
alwaysOutOfDate = 1;
@ -329,6 +383,45 @@
shellPath = /bin/sh;
shellScript = "\"$FLUTTER_ROOT\"/packages/flutter_tools/bin/macos_assemble.sh && touch Flutter/ephemeral/tripwire";
};
78F7E7C7FE2E75BBB3819847 /* [CP] Embed Pods Frameworks */ = {
isa = PBXShellScriptBuildPhase;
buildActionMask = 2147483647;
files = (
);
inputFileListPaths = (
"${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-frameworks-${CONFIGURATION}-input-files.xcfilelist",
);
name = "[CP] Embed Pods Frameworks";
outputFileListPaths = (
"${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-frameworks-${CONFIGURATION}-output-files.xcfilelist",
);
runOnlyForDeploymentPostprocessing = 0;
shellPath = /bin/sh;
shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-frameworks.sh\"\n";
showEnvVarsInLog = 0;
};
C86250B37FA1453AAEC9A1C2 /* [CP] Check Pods Manifest.lock */ = {
isa = PBXShellScriptBuildPhase;
buildActionMask = 2147483647;
files = (
);
inputFileListPaths = (
);
inputPaths = (
"${PODS_PODFILE_DIR_PATH}/Podfile.lock",
"${PODS_ROOT}/Manifest.lock",
);
name = "[CP] Check Pods Manifest.lock";
outputFileListPaths = (
);
outputPaths = (
"$(DERIVED_FILE_DIR)/Pods-Runner-checkManifestLockResult.txt",
);
runOnlyForDeploymentPostprocessing = 0;
shellPath = /bin/sh;
shellScript = "diff \"${PODS_PODFILE_DIR_PATH}/Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n# This output is used by Xcode 'outputs' to avoid re-running this script phase.\necho \"SUCCESS\" > \"${SCRIPT_OUTPUT_FILE_0}\"\n";
showEnvVarsInLog = 0;
};
/* End PBXShellScriptBuildPhase section */
/* Begin PBXSourcesBuildPhase section */
@ -380,6 +473,7 @@
/* Begin XCBuildConfiguration section */
331C80DB294CF71000263BE5 /* Debug */ = {
isa = XCBuildConfiguration;
baseConfigurationReference = A81A44EB7B90A16EAADE4FA6 /* Pods-RunnerTests.debug.xcconfig */;
buildSettings = {
BUNDLE_LOADER = "$(TEST_HOST)";
CURRENT_PROJECT_VERSION = 1;
@ -394,6 +488,7 @@
};
331C80DC294CF71000263BE5 /* Release */ = {
isa = XCBuildConfiguration;
baseConfigurationReference = 9D35F14235952B671983F7E0 /* Pods-RunnerTests.release.xcconfig */;
buildSettings = {
BUNDLE_LOADER = "$(TEST_HOST)";
CURRENT_PROJECT_VERSION = 1;
@ -408,6 +503,7 @@
};
331C80DD294CF71000263BE5 /* Profile */ = {
isa = XCBuildConfiguration;
baseConfigurationReference = A5B81D3E19756CB2D0C8B009 /* Pods-RunnerTests.profile.xcconfig */;
buildSettings = {
BUNDLE_LOADER = "$(TEST_HOST)";
CURRENT_PROJECT_VERSION = 1;

View File

@ -4,4 +4,7 @@
<FileRef
location = "group:Runner.xcodeproj">
</FileRef>
<FileRef
location = "group:Pods/Pods.xcodeproj">
</FileRef>
</Workspace>

View File

@ -53,6 +53,8 @@ dev_dependencies:
# package. See that file for information about deactivating specific lint
# rules and activating additional ones.
flutter_lints: ^6.0.0
integration_test:
sdk: flutter
# For information on the generic Dart part of this file, see the
# following page: https://dart.dev/tools/pub/pubspec

View File

@ -1,19 +0,0 @@
# Run with `dart run ffigen --config ffigen.yaml`.
name: CccCryptographyBindings
description: |
Bindings for `src/ccc_cryptography.h`.
Regenerate bindings with `dart run ffigen --config ffigen.yaml`.
output: 'lib/ccc_cryptography_bindings_generated.dart'
headers:
entry-points:
- 'src/ccc_cryptography.h'
include-directives:
- 'src/ccc_cryptography.h'
preamble: |
// ignore_for_file: always_specify_types
// ignore_for_file: camel_case_types
// ignore_for_file: non_constant_identifier_names
comments:
style: any
length: full

3
flutter_rust_bridge.yaml Normal file
View File

@ -0,0 +1,3 @@
rust_input: crate::api
dart_output: lib/src/rust
rust_root: rust/

View File

@ -1,3 +0,0 @@
// Relative import to be able to reuse the C sources.
// See the comment in ../ccc_cryptography.podspec for more information.
#include "../../src/ccc_cryptography.c"

1
ios/Classes/dummy_file.c Normal file
View File

@ -0,0 +1 @@
// This is an empty file to force CocoaPods to create a framework.

View File

@ -20,9 +20,26 @@ A new Flutter FFI plugin project.
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'
end
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 ccc_cryptography',
: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}/libccc_cryptography.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}/libccc_cryptography.a',
}
end

View File

@ -1,131 +1,147 @@
// The original content is temporarily commented out to allow generating a self-contained demo - feel free to uncomment later.
import 'dart:async';
import 'dart:ffi';
import 'dart:io';
import 'dart:isolate';
// // The original content is temporarily commented out to allow generating a self-contained demo - feel free to uncomment later.
//
// //
// // import 'dart:async';
// // import 'dart:ffi';
// // import 'dart:io';
// // import 'dart:isolate';
// //
// // import 'ccc_cryptography_bindings_generated.dart';
// //
// // /// A very short-lived native function.
// // ///
// // /// For very short-lived functions, it is fine to call them on the main isolate.
// // /// They will block the Dart execution while running the native function, so
// // /// only do this for native functions which are guaranteed to be short-lived.
// // int sum(int a, int b) => _bindings.sum(a, b);
// //
// // /// A longer lived native function, which occupies the thread calling it.
// // ///
// // /// Do not call these kind of native functions in the main isolate. They will
// // /// block Dart execution. This will cause dropped frames in Flutter applications.
// // /// Instead, call these native functions on a separate isolate.
// // ///
// // /// Modify this to suit your own use case. Example use cases:
// // ///
// // /// 1. Reuse a single isolate for various different kinds of requests.
// // /// 2. Use multiple helper isolates for parallel execution.
// // Future<int> sumAsync(int a, int b) async {
// // final SendPort helperIsolateSendPort = await _helperIsolateSendPort;
// // final int requestId = _nextSumRequestId++;
// // final _SumRequest request = _SumRequest(requestId, a, b);
// // final Completer<int> completer = Completer<int>();
// // _sumRequests[requestId] = completer;
// // helperIsolateSendPort.send(request);
// // return completer.future;
// // }
// //
// // const String _libName = 'ccc_cryptography';
// //
// // /// The dynamic library in which the symbols for [CccCryptographyBindings] can be found.
// // final DynamicLibrary _dylib = () {
// // if (Platform.isMacOS || Platform.isIOS) {
// // return DynamicLibrary.open('$_libName.framework/$_libName');
// // }
// // if (Platform.isAndroid || Platform.isLinux) {
// // return DynamicLibrary.open('lib$_libName.so');
// // }
// // if (Platform.isWindows) {
// // return DynamicLibrary.open('$_libName.dll');
// // }
// // throw UnsupportedError('Unknown platform: ${Platform.operatingSystem}');
// // }();
// //
// // /// The bindings to the native functions in [_dylib].
// // final CccCryptographyBindings _bindings = CccCryptographyBindings(_dylib);
// //
// //
// // /// A request to compute `sum`.
// // ///
// // /// Typically sent from one isolate to another.
// // class _SumRequest {
// // final int id;
// // final int a;
// // final int b;
// //
// // const _SumRequest(this.id, this.a, this.b);
// // }
// //
// // /// A response with the result of `sum`.
// // ///
// // /// Typically sent from one isolate to another.
// // class _SumResponse {
// // final int id;
// // final int result;
// //
// // const _SumResponse(this.id, this.result);
// // }
// //
// // /// Counter to identify [_SumRequest]s and [_SumResponse]s.
// // int _nextSumRequestId = 0;
// //
// // /// Mapping from [_SumRequest] `id`s to the completers corresponding to the correct future of the pending request.
// // final Map<int, Completer<int>> _sumRequests = <int, Completer<int>>{};
// //
// // /// The SendPort belonging to the helper isolate.
// // Future<SendPort> _helperIsolateSendPort = () async {
// // // The helper isolate is going to send us back a SendPort, which we want to
// // // wait for.
// // final Completer<SendPort> completer = Completer<SendPort>();
// //
// // // Receive port on the main isolate to receive messages from the helper.
// // // We receive two types of messages:
// // // 1. A port to send messages on.
// // // 2. Responses to requests we sent.
// // final ReceivePort receivePort = ReceivePort()
// // ..listen((dynamic data) {
// // if (data is SendPort) {
// // // The helper isolate sent us the port on which we can sent it requests.
// // completer.complete(data);
// // return;
// // }
// // if (data is _SumResponse) {
// // // The helper isolate sent us a response to a request we sent.
// // final Completer<int> completer = _sumRequests[data.id]!;
// // _sumRequests.remove(data.id);
// // completer.complete(data.result);
// // return;
// // }
// // throw UnsupportedError('Unsupported message type: ${data.runtimeType}');
// // });
// //
// // // Start the helper isolate.
// // await Isolate.spawn((SendPort sendPort) async {
// // final ReceivePort helperReceivePort = ReceivePort()
// // ..listen((dynamic data) {
// // // On the helper isolate listen to requests and respond to them.
// // if (data is _SumRequest) {
// // final int result = _bindings.sum_long_running(data.a, data.b);
// // final _SumResponse response = _SumResponse(data.id, result);
// // sendPort.send(response);
// // return;
// // }
// // throw UnsupportedError('Unsupported message type: ${data.runtimeType}');
// // });
// //
// // // Send the port to the main isolate on which we can receive requests.
// // sendPort.send(helperReceivePort.sendPort);
// // }, receivePort.sendPort);
// //
// // // Wait until the helper isolate has sent us back the SendPort on which we
// // // can start sending requests.
// // return completer.future;
// // }();
// //
//
// library ccc_cryptography;
//
// export 'src/rust/api/simple.dart';
// export 'src/rust/frb_generated.dart' show RustLib;
//
import 'ccc_cryptography_bindings_generated.dart';
library;
/// A very short-lived native function.
///
/// For very short-lived functions, it is fine to call them on the main isolate.
/// They will block the Dart execution while running the native function, so
/// only do this for native functions which are guaranteed to be short-lived.
int sum(int a, int b) => _bindings.sum(a, b);
/// A longer lived native function, which occupies the thread calling it.
///
/// Do not call these kind of native functions in the main isolate. They will
/// block Dart execution. This will cause dropped frames in Flutter applications.
/// Instead, call these native functions on a separate isolate.
///
/// Modify this to suit your own use case. Example use cases:
///
/// 1. Reuse a single isolate for various different kinds of requests.
/// 2. Use multiple helper isolates for parallel execution.
Future<int> sumAsync(int a, int b) async {
final SendPort helperIsolateSendPort = await _helperIsolateSendPort;
final int requestId = _nextSumRequestId++;
final _SumRequest request = _SumRequest(requestId, a, b);
final Completer<int> completer = Completer<int>();
_sumRequests[requestId] = completer;
helperIsolateSendPort.send(request);
return completer.future;
}
const String _libName = 'ccc_cryptography';
/// The dynamic library in which the symbols for [CccCryptographyBindings] can be found.
final DynamicLibrary _dylib = () {
if (Platform.isMacOS || Platform.isIOS) {
return DynamicLibrary.open('$_libName.framework/$_libName');
}
if (Platform.isAndroid || Platform.isLinux) {
return DynamicLibrary.open('lib$_libName.so');
}
if (Platform.isWindows) {
return DynamicLibrary.open('$_libName.dll');
}
throw UnsupportedError('Unknown platform: ${Platform.operatingSystem}');
}();
/// The bindings to the native functions in [_dylib].
final CccCryptographyBindings _bindings = CccCryptographyBindings(_dylib);
/// A request to compute `sum`.
///
/// Typically sent from one isolate to another.
class _SumRequest {
final int id;
final int a;
final int b;
const _SumRequest(this.id, this.a, this.b);
}
/// A response with the result of `sum`.
///
/// Typically sent from one isolate to another.
class _SumResponse {
final int id;
final int result;
const _SumResponse(this.id, this.result);
}
/// Counter to identify [_SumRequest]s and [_SumResponse]s.
int _nextSumRequestId = 0;
/// Mapping from [_SumRequest] `id`s to the completers corresponding to the correct future of the pending request.
final Map<int, Completer<int>> _sumRequests = <int, Completer<int>>{};
/// The SendPort belonging to the helper isolate.
Future<SendPort> _helperIsolateSendPort = () async {
// The helper isolate is going to send us back a SendPort, which we want to
// wait for.
final Completer<SendPort> completer = Completer<SendPort>();
// Receive port on the main isolate to receive messages from the helper.
// We receive two types of messages:
// 1. A port to send messages on.
// 2. Responses to requests we sent.
final ReceivePort receivePort = ReceivePort()
..listen((dynamic data) {
if (data is SendPort) {
// The helper isolate sent us the port on which we can sent it requests.
completer.complete(data);
return;
}
if (data is _SumResponse) {
// The helper isolate sent us a response to a request we sent.
final Completer<int> completer = _sumRequests[data.id]!;
_sumRequests.remove(data.id);
completer.complete(data.result);
return;
}
throw UnsupportedError('Unsupported message type: ${data.runtimeType}');
});
// Start the helper isolate.
await Isolate.spawn((SendPort sendPort) async {
final ReceivePort helperReceivePort = ReceivePort()
..listen((dynamic data) {
// On the helper isolate listen to requests and respond to them.
if (data is _SumRequest) {
final int result = _bindings.sum_long_running(data.a, data.b);
final _SumResponse response = _SumResponse(data.id, result);
sendPort.send(response);
return;
}
throw UnsupportedError('Unsupported message type: ${data.runtimeType}');
});
// Send the port to the main isolate on which we can receive requests.
sendPort.send(helperReceivePort.sendPort);
}, receivePort.sendPort);
// Wait until the helper isolate has sent us back the SendPort on which we
// can start sending requests.
return completer.future;
}();
export 'src/rust/api/simple.dart';
export 'src/rust/frb_generated.dart' show RustLib;

View File

@ -1,69 +0,0 @@
// ignore_for_file: always_specify_types
// ignore_for_file: camel_case_types
// ignore_for_file: non_constant_identifier_names
// AUTO GENERATED FILE, DO NOT EDIT.
//
// Generated by `package:ffigen`.
// ignore_for_file: type=lint
import 'dart:ffi' as ffi;
/// Bindings for `src/ccc_cryptography.h`.
///
/// Regenerate bindings with `dart run ffigen --config ffigen.yaml`.
///
class CccCryptographyBindings {
/// Holds the symbol lookup function.
final ffi.Pointer<T> Function<T extends ffi.NativeType>(String symbolName)
_lookup;
/// The symbols are looked up in [dynamicLibrary].
CccCryptographyBindings(ffi.DynamicLibrary dynamicLibrary)
: _lookup = dynamicLibrary.lookup;
/// The symbols are looked up with [lookup].
CccCryptographyBindings.fromLookup(
ffi.Pointer<T> Function<T extends ffi.NativeType>(String symbolName)
lookup)
: _lookup = lookup;
/// A very short-lived native function.
///
/// For very short-lived functions, it is fine to call them on the main isolate.
/// They will block the Dart execution while running the native function, so
/// only do this for native functions which are guaranteed to be short-lived.
int sum(
int a,
int b,
) {
return _sum(
a,
b,
);
}
late final _sumPtr =
_lookup<ffi.NativeFunction<ffi.Int Function(ffi.Int, ffi.Int)>>('sum');
late final _sum = _sumPtr.asFunction<int Function(int, int)>();
/// A longer lived native function, which occupies the thread calling it.
///
/// Do not call these kind of native functions in the main isolate. They will
/// block Dart execution. This will cause dropped frames in Flutter applications.
/// Instead, call these native functions on a separate isolate.
int sum_long_running(
int a,
int b,
) {
return _sum_long_running(
a,
b,
);
}
late final _sum_long_runningPtr =
_lookup<ffi.NativeFunction<ffi.Int Function(ffi.Int, ffi.Int)>>(
'sum_long_running');
late final _sum_long_running =
_sum_long_runningPtr.asFunction<int Function(int, int)>();
}

View File

@ -0,0 +1,10 @@
// 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';
String greet({required String name}) =>
RustLib.instance.api.crateApiSimpleGreet(name: name);

View File

@ -0,0 +1,242 @@
// This file is automatically generated, so please do not edit it.
// @generated by `flutter_rust_bridge`@ 2.11.1.
// ignore_for_file: unused_import, unused_element, unnecessary_import, duplicate_ignore, invalid_use_of_internal_member, annotate_overrides, non_constant_identifier_names, curly_braces_in_flow_control_structures, prefer_const_literals_to_create_immutables, unused_field
import 'api/simple.dart';
import 'dart:async';
import 'dart:convert';
import 'frb_generated.dart';
import 'frb_generated.io.dart'
if (dart.library.js_interop) 'frb_generated.web.dart';
import 'package:flutter_rust_bridge/flutter_rust_bridge_for_generated.dart';
/// Main entrypoint of the Rust API
class RustLib extends BaseEntrypoint<RustLibApi, RustLibApiImpl, RustLibWire> {
@internal
static final instance = RustLib._();
RustLib._();
/// Initialize flutter_rust_bridge
static Future<void> init({
RustLibApi? api,
BaseHandler? handler,
ExternalLibrary? externalLibrary,
bool forceSameCodegenVersion = true,
}) async {
await instance.initImpl(
api: api,
handler: handler,
externalLibrary: externalLibrary,
forceSameCodegenVersion: forceSameCodegenVersion,
);
}
/// Initialize flutter_rust_bridge in mock mode.
/// No libraries for FFI are loaded.
static void initMock({required RustLibApi api}) {
instance.initMockImpl(api: api);
}
/// Dispose flutter_rust_bridge
///
/// The call to this function is optional, since flutter_rust_bridge (and everything else)
/// is automatically disposed when the app stops.
static void dispose() => instance.disposeImpl();
@override
ApiImplConstructor<RustLibApiImpl, RustLibWire> get apiImplConstructor =>
RustLibApiImpl.new;
@override
WireConstructor<RustLibWire> get wireConstructor =>
RustLibWire.fromExternalLibrary;
@override
Future<void> executeRustInitializers() async {
await api.crateApiSimpleInitApp();
}
@override
ExternalLibraryLoaderConfig get defaultExternalLibraryLoaderConfig =>
kDefaultExternalLibraryLoaderConfig;
@override
String get codegenVersion => '2.11.1';
@override
int get rustContentHash => -1918914929;
static const kDefaultExternalLibraryLoaderConfig =
ExternalLibraryLoaderConfig(
stem: 'ccc_cryptography',
ioDirectory: 'rust/target/release/',
webPrefix: 'pkg/',
);
}
abstract class RustLibApi extends BaseApi {
String crateApiSimpleGreet({required String name});
Future<void> crateApiSimpleInitApp();
}
class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi {
RustLibApiImpl({
required super.handler,
required super.wire,
required super.generalizedFrbRustBinding,
required super.portManager,
});
@override
String crateApiSimpleGreet({required String name}) {
return handler.executeSync(
SyncTask(
callFfi: () {
final serializer = SseSerializer(generalizedFrbRustBinding);
sse_encode_String(name, serializer);
return pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 1)!;
},
codec: SseCodec(
decodeSuccessData: sse_decode_String,
decodeErrorData: null,
),
constMeta: kCrateApiSimpleGreetConstMeta,
argValues: [name],
apiImpl: this,
),
);
}
TaskConstMeta get kCrateApiSimpleGreetConstMeta =>
const TaskConstMeta(debugName: "greet", argNames: ["name"]);
@override
Future<void> crateApiSimpleInitApp() {
return handler.executeNormal(
NormalTask(
callFfi: (port_) {
final serializer = SseSerializer(generalizedFrbRustBinding);
pdeCallFfi(
generalizedFrbRustBinding,
serializer,
funcId: 2,
port: port_,
);
},
codec: SseCodec(
decodeSuccessData: sse_decode_unit,
decodeErrorData: null,
),
constMeta: kCrateApiSimpleInitAppConstMeta,
argValues: [],
apiImpl: this,
),
);
}
TaskConstMeta get kCrateApiSimpleInitAppConstMeta =>
const TaskConstMeta(debugName: "init_app", argNames: []);
@protected
String dco_decode_String(dynamic raw) {
// Codec=Dco (DartCObject based), see doc to use other codecs
return raw as String;
}
@protected
Uint8List dco_decode_list_prim_u_8_strict(dynamic raw) {
// Codec=Dco (DartCObject based), see doc to use other codecs
return raw as Uint8List;
}
@protected
int dco_decode_u_8(dynamic raw) {
// Codec=Dco (DartCObject based), see doc to use other codecs
return raw as int;
}
@protected
void dco_decode_unit(dynamic raw) {
// Codec=Dco (DartCObject based), see doc to use other codecs
return;
}
@protected
String sse_decode_String(SseDeserializer deserializer) {
// Codec=Sse (Serialization based), see doc to use other codecs
var inner = sse_decode_list_prim_u_8_strict(deserializer);
return utf8.decoder.convert(inner);
}
@protected
Uint8List sse_decode_list_prim_u_8_strict(SseDeserializer deserializer) {
// Codec=Sse (Serialization based), see doc to use other codecs
var len_ = sse_decode_i_32(deserializer);
return deserializer.buffer.getUint8List(len_);
}
@protected
int sse_decode_u_8(SseDeserializer deserializer) {
// Codec=Sse (Serialization based), see doc to use other codecs
return deserializer.buffer.getUint8();
}
@protected
void sse_decode_unit(SseDeserializer deserializer) {
// Codec=Sse (Serialization based), see doc to use other codecs
}
@protected
int sse_decode_i_32(SseDeserializer deserializer) {
// Codec=Sse (Serialization based), see doc to use other codecs
return deserializer.buffer.getInt32();
}
@protected
bool sse_decode_bool(SseDeserializer deserializer) {
// Codec=Sse (Serialization based), see doc to use other codecs
return deserializer.buffer.getUint8() != 0;
}
@protected
void sse_encode_String(String self, SseSerializer serializer) {
// Codec=Sse (Serialization based), see doc to use other codecs
sse_encode_list_prim_u_8_strict(utf8.encoder.convert(self), serializer);
}
@protected
void sse_encode_list_prim_u_8_strict(
Uint8List self,
SseSerializer serializer,
) {
// Codec=Sse (Serialization based), see doc to use other codecs
sse_encode_i_32(self.length, serializer);
serializer.buffer.putUint8List(self);
}
@protected
void sse_encode_u_8(int self, SseSerializer serializer) {
// Codec=Sse (Serialization based), see doc to use other codecs
serializer.buffer.putUint8(self);
}
@protected
void sse_encode_unit(void self, SseSerializer serializer) {
// Codec=Sse (Serialization based), see doc to use other codecs
}
@protected
void sse_encode_i_32(int self, SseSerializer serializer) {
// Codec=Sse (Serialization based), see doc to use other codecs
serializer.buffer.putInt32(self);
}
@protected
void sse_encode_bool(bool self, SseSerializer serializer) {
// Codec=Sse (Serialization based), see doc to use other codecs
serializer.buffer.putUint8(self ? 1 : 0);
}
}

View File

@ -0,0 +1,86 @@
// This file is automatically generated, so please do not edit it.
// @generated by `flutter_rust_bridge`@ 2.11.1.
// ignore_for_file: unused_import, unused_element, unnecessary_import, duplicate_ignore, invalid_use_of_internal_member, annotate_overrides, non_constant_identifier_names, curly_braces_in_flow_control_structures, prefer_const_literals_to_create_immutables, unused_field
import 'api/simple.dart';
import 'dart:async';
import 'dart:convert';
import 'dart:ffi' as ffi;
import 'frb_generated.dart';
import 'package:flutter_rust_bridge/flutter_rust_bridge_for_generated_io.dart';
abstract class RustLibApiImplPlatform extends BaseApiImpl<RustLibWire> {
RustLibApiImplPlatform({
required super.handler,
required super.wire,
required super.generalizedFrbRustBinding,
required super.portManager,
});
@protected
String dco_decode_String(dynamic raw);
@protected
Uint8List dco_decode_list_prim_u_8_strict(dynamic raw);
@protected
int dco_decode_u_8(dynamic raw);
@protected
void dco_decode_unit(dynamic raw);
@protected
String sse_decode_String(SseDeserializer deserializer);
@protected
Uint8List sse_decode_list_prim_u_8_strict(SseDeserializer deserializer);
@protected
int sse_decode_u_8(SseDeserializer deserializer);
@protected
void sse_decode_unit(SseDeserializer deserializer);
@protected
int sse_decode_i_32(SseDeserializer deserializer);
@protected
bool sse_decode_bool(SseDeserializer deserializer);
@protected
void sse_encode_String(String self, SseSerializer serializer);
@protected
void sse_encode_list_prim_u_8_strict(
Uint8List self,
SseSerializer serializer,
);
@protected
void sse_encode_u_8(int self, SseSerializer serializer);
@protected
void sse_encode_unit(void self, SseSerializer serializer);
@protected
void sse_encode_i_32(int self, SseSerializer serializer);
@protected
void sse_encode_bool(bool self, SseSerializer serializer);
}
// Section: wire_class
class RustLibWire implements BaseWire {
factory RustLibWire.fromExternalLibrary(ExternalLibrary lib) =>
RustLibWire(lib.ffiDynamicLibrary);
/// Holds the symbol lookup function.
final ffi.Pointer<T> Function<T extends ffi.NativeType>(String symbolName)
_lookup;
/// The symbols are looked up in [dynamicLibrary].
RustLibWire(ffi.DynamicLibrary dynamicLibrary)
: _lookup = dynamicLibrary.lookup;
}

View File

@ -0,0 +1,86 @@
// This file is automatically generated, so please do not edit it.
// @generated by `flutter_rust_bridge`@ 2.11.1.
// ignore_for_file: unused_import, unused_element, unnecessary_import, duplicate_ignore, invalid_use_of_internal_member, annotate_overrides, non_constant_identifier_names, curly_braces_in_flow_control_structures, prefer_const_literals_to_create_immutables, unused_field
// Static analysis wrongly picks the IO variant, thus ignore this
// ignore_for_file: argument_type_not_assignable
import 'api/simple.dart';
import 'dart:async';
import 'dart:convert';
import 'frb_generated.dart';
import 'package:flutter_rust_bridge/flutter_rust_bridge_for_generated_web.dart';
abstract class RustLibApiImplPlatform extends BaseApiImpl<RustLibWire> {
RustLibApiImplPlatform({
required super.handler,
required super.wire,
required super.generalizedFrbRustBinding,
required super.portManager,
});
@protected
String dco_decode_String(dynamic raw);
@protected
Uint8List dco_decode_list_prim_u_8_strict(dynamic raw);
@protected
int dco_decode_u_8(dynamic raw);
@protected
void dco_decode_unit(dynamic raw);
@protected
String sse_decode_String(SseDeserializer deserializer);
@protected
Uint8List sse_decode_list_prim_u_8_strict(SseDeserializer deserializer);
@protected
int sse_decode_u_8(SseDeserializer deserializer);
@protected
void sse_decode_unit(SseDeserializer deserializer);
@protected
int sse_decode_i_32(SseDeserializer deserializer);
@protected
bool sse_decode_bool(SseDeserializer deserializer);
@protected
void sse_encode_String(String self, SseSerializer serializer);
@protected
void sse_encode_list_prim_u_8_strict(
Uint8List self,
SseSerializer serializer,
);
@protected
void sse_encode_u_8(int self, SseSerializer serializer);
@protected
void sse_encode_unit(void self, SseSerializer serializer);
@protected
void sse_encode_i_32(int self, SseSerializer serializer);
@protected
void sse_encode_bool(bool self, SseSerializer serializer);
}
// Section: wire_class
class RustLibWire implements BaseWire {
RustLibWire.fromExternalLibrary(ExternalLibrary lib);
}
@JS('wasm_bindgen')
external RustLibWasmModule get wasmModule;
@JS()
@anonymous
extension type RustLibWasmModule._(JSObject _) implements JSObject {}

View File

@ -7,16 +7,13 @@ cmake_minimum_required(VERSION 3.10)
set(PROJECT_NAME "ccc_cryptography")
project(${PROJECT_NAME} LANGUAGES CXX)
# Invoke the build for native code shared with the other target platforms.
# This can be changed to accommodate different builds.
add_subdirectory("${CMAKE_CURRENT_SOURCE_DIR}/../src" "${CMAKE_CURRENT_BINARY_DIR}/shared")
include("../cargokit/cmake/cargokit.cmake")
apply_cargokit(${PROJECT_NAME} ../rust ccc_cryptography "")
# 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(ccc_cryptography_bundled_libraries
# Defined in ../src/CMakeLists.txt.
# This can be changed to accommodate different builds.
$<TARGET_FILE:ccc_cryptography>
"${${PROJECT_NAME}_cargokit_lib}"
PARENT_SCOPE
)

View File

@ -1,3 +0,0 @@
// Relative import to be able to reuse the C sources.
// See the comment in ../ccc_cryptography.podspec for more information.
#include "../../src/ccc_cryptography.c"

View File

@ -0,0 +1 @@
// This is an empty file to force CocoaPods to create a framework.

View File

@ -18,17 +18,27 @@ A new Flutter FFI plugin project.
# 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 = {'ccc_cryptography_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'
end
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 ccc_cryptography',
: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}/libccc_cryptography.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}/libccc_cryptography.a',
}
end

View File

@ -1,7 +1,7 @@
name: ccc_cryptography
description: "Copius Cipher Chain Cryptography"
publish_to: 'none'
version: 0.0.1
homepage:
environment:
sdk: ^3.10.1
@ -11,13 +11,19 @@ dependencies:
flutter:
sdk: flutter
plugin_platform_interface: ^2.0.2
flutter_rust_bridge: 2.11.1
freezed_annotation: ^2.4.1
meta: ^1.11.0
dev_dependencies:
ffi: ^2.1.3
ffigen: ^13.0.0
flutter_test:
sdk: flutter
flutter_lints: ^6.0.0
build_runner: ^2.4.8
freezed: ^2.5.2
integration_test:
sdk: flutter
flutter:
plugin:

1
rust/.gitignore vendored Normal file
View File

@ -0,0 +1 @@
/target

15
rust/Cargo.toml Normal file
View File

@ -0,0 +1,15 @@
[package]
name = "ccc_cryptography"
version = "0.1.0"
edition = "2021"
[lib]
crate-type = ["cdylib", "staticlib"]
[dependencies]
# Local dev paths — switch to git deps for CI/release:
# ccc-crypto-core = { git = "ssh://git@10.0.5.109/j3g/lum_ccc_rust.git", rev = "971f1ae" }
# ccc-crypto-wolfssl = { git = "ssh://git@10.0.5.109/j3g/lum_ccc_rust.git", rev = "971f1ae" }
ccc-crypto-core = { path = "/Volumes/LUM/source/letusmsg_proj/app/lum_ccc_rust/crates/ccc-crypto-core" }
ccc-crypto-wolfssl = { path = "/Volumes/LUM/source/letusmsg_proj/app/lum_ccc_rust/crates/ccc-crypto-wolfssl" }
flutter_rust_bridge = "=2.11.1"

1
rust/src/api/mod.rs Normal file
View File

@ -0,0 +1 @@
pub mod simple;

10
rust/src/api/simple.rs Normal file
View File

@ -0,0 +1,10 @@
#[flutter_rust_bridge::frb(sync)] // Synchronous mode for simplicity of the demo
pub fn greet(name: String) -> String {
format!("Hello, {name}!")
}
#[flutter_rust_bridge::frb(init)]
pub fn init_app() {
// Default utilities - feel free to customize
flutter_rust_bridge::setup_default_user_utils();
}

276
rust/src/frb_generated.rs Normal file
View File

@ -0,0 +1,276 @@
// This file is automatically generated, so please do not edit it.
// @generated by `flutter_rust_bridge`@ 2.11.1.
#![allow(
non_camel_case_types,
unused,
non_snake_case,
clippy::needless_return,
clippy::redundant_closure_call,
clippy::redundant_closure,
clippy::useless_conversion,
clippy::unit_arg,
clippy::unused_unit,
clippy::double_parens,
clippy::let_and_return,
clippy::too_many_arguments,
clippy::match_single_binding,
clippy::clone_on_copy,
clippy::let_unit_value,
clippy::deref_addrof,
clippy::explicit_auto_deref,
clippy::borrow_deref_ref,
clippy::needless_borrow
)]
// Section: imports
use flutter_rust_bridge::for_generated::byteorder::{NativeEndian, ReadBytesExt, WriteBytesExt};
use flutter_rust_bridge::for_generated::{transform_result_dco, Lifetimeable, Lockable};
use flutter_rust_bridge::{Handler, IntoIntoDart};
// Section: boilerplate
flutter_rust_bridge::frb_generated_boilerplate!(
default_stream_sink_codec = SseCodec,
default_rust_opaque = RustOpaqueMoi,
default_rust_auto_opaque = RustAutoOpaqueMoi,
);
pub(crate) const FLUTTER_RUST_BRIDGE_CODEGEN_VERSION: &str = "2.11.1";
pub(crate) const FLUTTER_RUST_BRIDGE_CODEGEN_CONTENT_HASH: i32 = -1918914929;
// Section: executor
flutter_rust_bridge::frb_generated_default_handler!();
// Section: wire_funcs
fn wire__crate__api__simple__greet_impl(
ptr_: flutter_rust_bridge::for_generated::PlatformGeneralizedUint8ListPtr,
rust_vec_len_: i32,
data_len_: i32,
) -> flutter_rust_bridge::for_generated::WireSyncRust2DartSse {
FLUTTER_RUST_BRIDGE_HANDLER.wrap_sync::<flutter_rust_bridge::for_generated::SseCodec, _>(
flutter_rust_bridge::for_generated::TaskInfo {
debug_name: "greet",
port: None,
mode: flutter_rust_bridge::for_generated::FfiCallMode::Sync,
},
move || {
let message = unsafe {
flutter_rust_bridge::for_generated::Dart2RustMessageSse::from_wire(
ptr_,
rust_vec_len_,
data_len_,
)
};
let mut deserializer =
flutter_rust_bridge::for_generated::SseDeserializer::new(message);
let api_name = <String>::sse_decode(&mut deserializer);
deserializer.end();
transform_result_sse::<_, ()>((move || {
let output_ok = Result::<_, ()>::Ok(crate::api::simple::greet(api_name))?;
Ok(output_ok)
})())
},
)
}
fn wire__crate__api__simple__init_app_impl(
port_: flutter_rust_bridge::for_generated::MessagePort,
ptr_: flutter_rust_bridge::for_generated::PlatformGeneralizedUint8ListPtr,
rust_vec_len_: i32,
data_len_: i32,
) {
FLUTTER_RUST_BRIDGE_HANDLER.wrap_normal::<flutter_rust_bridge::for_generated::SseCodec, _, _>(
flutter_rust_bridge::for_generated::TaskInfo {
debug_name: "init_app",
port: Some(port_),
mode: flutter_rust_bridge::for_generated::FfiCallMode::Normal,
},
move || {
let message = unsafe {
flutter_rust_bridge::for_generated::Dart2RustMessageSse::from_wire(
ptr_,
rust_vec_len_,
data_len_,
)
};
let mut deserializer =
flutter_rust_bridge::for_generated::SseDeserializer::new(message);
deserializer.end();
move |context| {
transform_result_sse::<_, ()>((move || {
let output_ok = Result::<_, ()>::Ok({
crate::api::simple::init_app();
})?;
Ok(output_ok)
})())
}
},
)
}
// Section: dart2rust
impl SseDecode for String {
// Codec=Sse (Serialization based), see doc to use other codecs
fn sse_decode(deserializer: &mut flutter_rust_bridge::for_generated::SseDeserializer) -> Self {
let mut inner = <Vec<u8>>::sse_decode(deserializer);
return String::from_utf8(inner).unwrap();
}
}
impl SseDecode for Vec<u8> {
// Codec=Sse (Serialization based), see doc to use other codecs
fn sse_decode(deserializer: &mut flutter_rust_bridge::for_generated::SseDeserializer) -> Self {
let mut len_ = <i32>::sse_decode(deserializer);
let mut ans_ = vec![];
for idx_ in 0..len_ {
ans_.push(<u8>::sse_decode(deserializer));
}
return ans_;
}
}
impl SseDecode for u8 {
// Codec=Sse (Serialization based), see doc to use other codecs
fn sse_decode(deserializer: &mut flutter_rust_bridge::for_generated::SseDeserializer) -> Self {
deserializer.cursor.read_u8().unwrap()
}
}
impl SseDecode for () {
// Codec=Sse (Serialization based), see doc to use other codecs
fn sse_decode(deserializer: &mut flutter_rust_bridge::for_generated::SseDeserializer) -> Self {}
}
impl SseDecode for i32 {
// Codec=Sse (Serialization based), see doc to use other codecs
fn sse_decode(deserializer: &mut flutter_rust_bridge::for_generated::SseDeserializer) -> Self {
deserializer.cursor.read_i32::<NativeEndian>().unwrap()
}
}
impl SseDecode for bool {
// Codec=Sse (Serialization based), see doc to use other codecs
fn sse_decode(deserializer: &mut flutter_rust_bridge::for_generated::SseDeserializer) -> Self {
deserializer.cursor.read_u8().unwrap() != 0
}
}
fn pde_ffi_dispatcher_primary_impl(
func_id: i32,
port: flutter_rust_bridge::for_generated::MessagePort,
ptr: flutter_rust_bridge::for_generated::PlatformGeneralizedUint8ListPtr,
rust_vec_len: i32,
data_len: i32,
) {
// Codec=Pde (Serialization + dispatch), see doc to use other codecs
match func_id {
2 => wire__crate__api__simple__init_app_impl(port, ptr, rust_vec_len, data_len),
_ => unreachable!(),
}
}
fn pde_ffi_dispatcher_sync_impl(
func_id: i32,
ptr: flutter_rust_bridge::for_generated::PlatformGeneralizedUint8ListPtr,
rust_vec_len: i32,
data_len: i32,
) -> flutter_rust_bridge::for_generated::WireSyncRust2DartSse {
// Codec=Pde (Serialization + dispatch), see doc to use other codecs
match func_id {
1 => wire__crate__api__simple__greet_impl(ptr, rust_vec_len, data_len),
_ => unreachable!(),
}
}
// Section: rust2dart
impl SseEncode for String {
// Codec=Sse (Serialization based), see doc to use other codecs
fn sse_encode(self, serializer: &mut flutter_rust_bridge::for_generated::SseSerializer) {
<Vec<u8>>::sse_encode(self.into_bytes(), serializer);
}
}
impl SseEncode for Vec<u8> {
// Codec=Sse (Serialization based), see doc to use other codecs
fn sse_encode(self, serializer: &mut flutter_rust_bridge::for_generated::SseSerializer) {
<i32>::sse_encode(self.len() as _, serializer);
for item in self {
<u8>::sse_encode(item, serializer);
}
}
}
impl SseEncode for u8 {
// Codec=Sse (Serialization based), see doc to use other codecs
fn sse_encode(self, serializer: &mut flutter_rust_bridge::for_generated::SseSerializer) {
serializer.cursor.write_u8(self).unwrap();
}
}
impl SseEncode for () {
// Codec=Sse (Serialization based), see doc to use other codecs
fn sse_encode(self, serializer: &mut flutter_rust_bridge::for_generated::SseSerializer) {}
}
impl SseEncode for i32 {
// Codec=Sse (Serialization based), see doc to use other codecs
fn sse_encode(self, serializer: &mut flutter_rust_bridge::for_generated::SseSerializer) {
serializer.cursor.write_i32::<NativeEndian>(self).unwrap();
}
}
impl SseEncode for bool {
// Codec=Sse (Serialization based), see doc to use other codecs
fn sse_encode(self, serializer: &mut flutter_rust_bridge::for_generated::SseSerializer) {
serializer.cursor.write_u8(self as _).unwrap();
}
}
#[cfg(not(target_family = "wasm"))]
mod io {
// This file is automatically generated, so please do not edit it.
// @generated by `flutter_rust_bridge`@ 2.11.1.
// Section: imports
use super::*;
use flutter_rust_bridge::for_generated::byteorder::{
NativeEndian, ReadBytesExt, WriteBytesExt,
};
use flutter_rust_bridge::for_generated::{transform_result_dco, Lifetimeable, Lockable};
use flutter_rust_bridge::{Handler, IntoIntoDart};
// Section: boilerplate
flutter_rust_bridge::frb_generated_boilerplate_io!();
}
#[cfg(not(target_family = "wasm"))]
pub use io::*;
/// cbindgen:ignore
#[cfg(target_family = "wasm")]
mod web {
// This file is automatically generated, so please do not edit it.
// @generated by `flutter_rust_bridge`@ 2.11.1.
// Section: imports
use super::*;
use flutter_rust_bridge::for_generated::byteorder::{
NativeEndian, ReadBytesExt, WriteBytesExt,
};
use flutter_rust_bridge::for_generated::wasm_bindgen;
use flutter_rust_bridge::for_generated::wasm_bindgen::prelude::*;
use flutter_rust_bridge::for_generated::{transform_result_dco, Lifetimeable, Lockable};
use flutter_rust_bridge::{Handler, IntoIntoDart};
// Section: boilerplate
flutter_rust_bridge::frb_generated_boilerplate_web!();
}
#[cfg(target_family = "wasm")]
pub use web::*;

2
rust/src/lib.rs Normal file
View File

@ -0,0 +1,2 @@
mod api;
mod frb_generated;

View File

@ -1,22 +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(ccc_cryptography_library VERSION 0.0.1 LANGUAGES C)
add_library(ccc_cryptography SHARED
"ccc_cryptography.c"
)
set_target_properties(ccc_cryptography PROPERTIES
PUBLIC_HEADER ccc_cryptography.h
OUTPUT_NAME "ccc_cryptography"
)
target_compile_definitions(ccc_cryptography PUBLIC DART_SHARED_LIB)
if (ANDROID)
# Support Android 15 16k page size
target_link_options(ccc_cryptography PRIVATE "-Wl,-z,max-page-size=16384")
endif()

View File

@ -1,23 +0,0 @@
#include "ccc_cryptography.h"
// A very short-lived native function.
//
// For very short-lived functions, it is fine to call them on the main isolate.
// They will block the Dart execution while running the native function, so
// only do this for native functions which are guaranteed to be short-lived.
FFI_PLUGIN_EXPORT int sum(int a, int b) { return a + b; }
// A longer-lived native function, which occupies the thread calling it.
//
// Do not call these kind of native functions in the main isolate. They will
// block Dart execution. This will cause dropped frames in Flutter applications.
// Instead, call these native functions on a separate isolate.
FFI_PLUGIN_EXPORT int sum_long_running(int a, int b) {
// Simulate work.
#if _WIN32
Sleep(5000);
#else
usleep(5000 * 1000);
#endif
return a + b;
}

View File

@ -1,30 +0,0 @@
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#if _WIN32
#include <windows.h>
#else
#include <pthread.h>
#include <unistd.h>
#endif
#if _WIN32
#define FFI_PLUGIN_EXPORT __declspec(dllexport)
#else
#define FFI_PLUGIN_EXPORT
#endif
// A very short-lived native function.
//
// For very short-lived functions, it is fine to call them on the main isolate.
// They will block the Dart execution while running the native function, so
// only do this for native functions which are guaranteed to be short-lived.
FFI_PLUGIN_EXPORT int sum(int a, int b);
// A longer lived native function, which occupies the thread calling it.
//
// Do not call these kind of native functions in the main isolate. They will
// block Dart execution. This will cause dropped frames in Flutter applications.
// Instead, call these native functions on a separate isolate.
FFI_PLUGIN_EXPORT int sum_long_running(int a, int b);

View File

@ -0,0 +1,3 @@
import 'package:integration_test/integration_test_driver.dart';
Future<void> main() => integrationDriver();

View File

@ -8,16 +8,13 @@ cmake_minimum_required(VERSION 3.14)
set(PROJECT_NAME "ccc_cryptography")
project(${PROJECT_NAME} LANGUAGES CXX)
# Invoke the build for native code shared with the other target platforms.
# This can be changed to accommodate different builds.
add_subdirectory("${CMAKE_CURRENT_SOURCE_DIR}/../src" "${CMAKE_CURRENT_BINARY_DIR}/shared")
include("../cargokit/cmake/cargokit.cmake")
apply_cargokit(${PROJECT_NAME} ../rust ccc_cryptography "")
# 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(ccc_cryptography_bundled_libraries
# Defined in ../src/CMakeLists.txt.
# This can be changed to accommodate different builds.
$<TARGET_FILE:ccc_cryptography>
"${${PROJECT_NAME}_cargokit_lib}"
PARENT_SCOPE
)