lum_ccc_rust/docs/ccc_rust_plan.rst

449 lines
17 KiB
ReStructuredText
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

===============================================
CCC Rust Crypto Provider — Architecture Plan
===============================================
:Status: Approved
:Phase: 4
:Date: 2026-02-23
:Author: Engineering
Overview
--------
Replace the Dart-only crypto stubs with a Cargo workspace of native Rust
crates. A shared trait/capability core defines the contract every provider
must satisfy. Per-provider sub-crates implement that contract.
``flutter_rust_bridge`` auto-generates ``dart:ffi`` bindings so Dart code
calls Rust directly with no platform-channel overhead. wolfSSL / wolfCrypt
is the first (and only Phase 4) provider. All future libraries slot into the
same trait with zero changes to the core.
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 already in
``cipher_constants.dart`` — zero Dart routing changes needed.
3. Key material is zeroed on drop (``zeroize`` crate) everywhere.
4. A conformance / self-test suite validates cross-provider byte-identity
before any provider is marked ``available``.
5. The Rust workspace has no runtime dependency on Flutter; it is a pure
native library that could be consumed by any FFI host.
FFI Bridge Decision
-------------------
``flutter_rust_bridge`` (FRB) is used rather than raw ``dart:ffi`` hand-wiring.
FRB **is** ``dart:ffi`` — it uses ``dart:ffi`` under the hood and introduces
no platform channels. The difference from raw ``dart:ffi`` is:
========================= ========================== ==========================
Aspect flutter_rust_bridge Raw dart:ffi
========================= ========================== ==========================
Rust-side code Clean idiomatic Rust ``extern "C"`` with C ABI
Dart bindings **Auto-generated** Hand-written every field
Async / isolate support Automatic Manual wiring
Cross-type safety Codegen validates at build Discovered at runtime
Beginner-friendliness High Low
========================= ========================== ==========================
Repository Layout (target state)
---------------------------------
::
ccc_rust/
├── Cargo.toml ← workspace manifest (3 members)
├── 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 impl
│ │ ├── Cargo.toml
│ │ └── src/
│ │ ├── lib.rs
│ │ ├── aead.rs ← AES-256-GCM, ChaCha20-Poly1305
│ │ ├── kdf.rs ← HKDF, Argon2id
│ │ ├── mac.rs ← HMAC-SHA256/384/512
│ │ ├── hash.rs ← SHA-2, SHA-3, BLAKE2b
│ │ ├── kem.rs ← X25519, X448, ML-KEM (if PQ build)
│ │ ├── capabilities.rs ← probe-at-startup + benchmark
│ │ └── provider.rs ← WolfSslProvider: CryptoProvider impl
│ └── ccc-flutter-bridge/ ← flutter_rust_bridge entry point
│ ├── Cargo.toml
│ └── src/
│ ├── lib.rs
│ ├── bridge.rs ← #[frb] exported functions
│ └── dto.rs ← CapabilitiesDto, KemKeyPairDto, SelfTestDto
├── tests/
│ └── conformance/
│ ├── aes_gcm_vectors.rs
│ ├── chacha_vectors.rs
│ ├── hkdf_vectors.rs
│ ├── hmac_vectors.rs
│ └── cross_provider.rs
├── flutter_src/
│ └── ccc/ ← existing Dart files (minimal changes)
└── docs/
Step 1 — Cargo Workspace Scaffold
----------------------------------
Files
~~~~~
``Cargo.toml``::
[workspace]
resolver = "2"
members = [
"crates/ccc-crypto-core",
"crates/ccc-crypto-wolfssl",
"crates/ccc-flutter-bridge",
]
``rust-toolchain.toml``::
[toolchain]
channel = "1.77"
``.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``
-----------------------------------------------------
Submodule Registration::
git submodule add https://github.com/wolfSSL/wolfssl vendors/wolfssl
git -C vendors/wolfssl checkout v5.7.2-stable
``crates/ccc-crypto-wolfssl/Cargo.toml`` key dependencies::
wolfssl = { version = "0.1", features = ["pq", "blake2", "argon2"] }
zeroize = { version = "1", features = ["derive"] }
ccc-crypto-core = { path = "../ccc-crypto-core" }
wolfSSL Phase 4 Algorithm Coverage
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
=================== ===========================================
Category Algorithms
=================== ===========================================
AEAD AES-256-GCM, ChaCha20-Poly1305
KDF HKDF-SHA256/384/512, PBKDF2, Argon2id
MAC HMAC-SHA256/384/512, Poly1305
Hash SHA-256/384/512, SHA3-256/512, BLAKE2b-512
KEM (if PQ build) X25519, X448, ML-KEM-768, ML-KEM-1024
=================== ===========================================
Capability Probe Strategy
~~~~~~~~~~~~~~~~~~~~~~~~~~
``WolfSslProvider::capabilities()`` runs a minimal probe call per algorithm at
startup (encrypt 1-byte payload; decrypt; compare). Sets
``available = probe_succeeded``. If the wolfSSL build does not include PQ
support, ML-KEM entries gracefully report ``available: false``.
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 ``ccc_init()`` and cached.
Step 4 — ``ccc-flutter-bridge`` Entry-Point Crate
---------------------------------------------------
Exported Functions (``#[frb]`` tagged)
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
.. code-block:: text
ccc_init() → initialise registry + run benchmarks
ccc_list_providers() → Vec<String>
ccc_provider_capabilities(provider) → CapabilitiesDto
ccc_aead_encrypt(provider, algo: u32, key, nonce, plaintext, aad)
→ Result<Vec<u8>>
ccc_aead_decrypt(provider, algo: u32, key, nonce, ciphertext, aad)
→ Result<Vec<u8>>
ccc_derive_key(provider, algo: u32, ikm, salt, info, length: u32)
→ Result<Vec<u8>>
ccc_compute_mac(provider, algo: u32, key, data)
→ Result<Vec<u8>>
ccc_verify_mac(provider, algo: u32, key, data, mac)
→ Result<bool>
ccc_hash(provider, algo: u32, data) → Result<Vec<u8>>
ccc_kem_generate_keypair(provider, algo: u32)
→ Result<KemKeyPairDto>
ccc_kem_encapsulate(provider, algo: u32, public_key)
→ Result<KemEncapDto>
ccc_kem_decapsulate(provider, algo: u32, private_key, ciphertext)
→ Result<Vec<u8>>
ccc_self_test(provider) → SelfTestDto
DTO Structs
~~~~~~~~~~~
``CapabilitiesDto`` — mirrors ``ProviderCapabilities``, uses primitive types
so ``flutter_rust_bridge`` can auto-generate the Dart data class.
``KemKeyPairDto { public_key: Vec<u8>, private_key: Vec<u8> }``
``KemEncapDto { ciphertext: Vec<u8>, shared_secret: Vec<u8> }``
``SelfTestDto { provider: String, results: Vec<AlgoTestResult> }``
``AlgoTestResult { algo_id: u32, algo_name: String, passed: bool,
error_message: Option<String> }``
Step 5 — Flutter Build Integration
------------------------------------
* Add ``flutter_rust_bridge: ^2`` to ``pubspec.yaml``
* Run ``flutter_rust_bridge_codegen generate`` → emits
``flutter_src/ccc_crypto_bindings/ccc_crypto.dart``
* ``crate-type = ["cdylib", "staticlib"]`` in ``ccc-flutter-bridge/Cargo.toml``
(``cdylib`` for Android / Linux / macOS, ``staticlib`` for iOS)
* Cargokit handles cross-compilation inside standard Flutter plugin dirs
(``ios/``, ``android/``, ``macos/``)
Step 6 — Dart Layer Wiring
---------------------------
``crypto_wolfssl.dart``
~~~~~~~~~~~~~~~~~~~~~~~~
Replace ``UnimplementedError`` stubs:
.. code-block:: dart
@override
Future<List<int>> encrypt(Map<String, dynamic> input,
{CryptoContext? context}) async {
final algo = context?.cipherSequence?.first ?? CipherConstants.AES_GCM_256;
final key = _resolveKey(context);
final nonce = _generateNonce(algo);
return CccCrypto.ccmAeadEncrypt(
provider: 'wolfssl', algo: algo,
key: key, nonce: nonce,
plaintext: _encodePayload(input), aad: _buildAad(context));
}
``ccc_provider_spec.dart``
~~~~~~~~~~~~~~~~~~~~~~~~~~~
Convert ``CccProviderCatalog.capabilities`` from a compile-time static map to a
runtime-populated map. At app start call::
await CccCrypto.cccInit();
final providers = await CccCrypto.cccListProviders();
for (final name in providers) {
final dto = await CccCrypto.cccProviderCapabilities(provider: name);
CccProviderCatalog.populate(name, dto);
}
``CccSelfTest``
~~~~~~~~~~~~~~~~
New Dart class that wraps ``CccCrypto.cccSelfTest(provider: name)`` and exposes
per-algorithm pass/fail results in the app's debug diagnostics screen.
Step 7 — Conformance Test Suite
---------------------------------
Location: ``tests/conformance/``
* ``aes_gcm_vectors.rs`` — NIST SP 800-38D GCM test vectors
* ``chacha_vectors.rs`` — RFC 8439 ChaCha20-Poly1305 test vectors
* ``hkdf_vectors.rs`` — RFC 5869 HKDF-SHA256 / SHA512 test vectors
* ``hmac_vectors.rs`` — RFC 4231 HMAC-SHA256 / SHA512 test vectors
* ``cross_provider.rs`` — encrypt with wolfSSL → decrypt expectation matches
the reference output from the Dart ``cryptography`` package for the same
key/nonce/plaintext/aad (validates ``deterministic_io: true``)
Step 8 — Architecture Documentation
--------------------------------------
``docs/phase4_rust_architecture.rst`` covers:
* Crate dependency graph (ASCII)
* "How to add a new provider" — the 7-step trait checklist
* ``algo: u32`` → cipher constant mapping table
* Stretch-goal Phase 8 "Omni-Crypto" provider list
Phase 8 — Stretch Goal Provider List
--------------------------------------
*(Fully out of scope for Phase 4. Documented here for future planning.)*
================== =====================================================
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
================== =====================================================
Verification Checklist
-----------------------
* ``cargo test --workspace`` passes including all NIST vectors
* ``cargo build --target aarch64-apple-ios`` succeeds
* ``cargo build --target aarch64-linux-android`` succeeds
* Flutter integration test: roundtrip encrypt/decrypt 1 KB via
``CryptoWolfSsl`` Dart class
* ``CccSelfTest.runAll()`` returns all-pass in the app debug screen
* Cross-provider conformance: Dart ↔ wolfSSL byte-identity confirmed
(``deterministic_io: true`` verified for AES-256-GCM and ChaCha20-Poly1305)