CCC Cryptography Plugin — Milestone 3 App Integration ====================================================== :Created: 2026-03-16 :Status: Ready to Begin (API frozen; Windows + Linux tests deferred) :Audience: LetUsMsg application team :Plugin package: ``ccc_cryptography`` :Plugin version: ``0.0.1`` (pre-tag; ``v0.1.0`` tag pending) :Milestone: 3 of 3 Overview -------- This document describes how the **LetUsMsg** application integrates the ``ccc_cryptography`` Flutter plugin. Milestone 2 delivered a fully tested Flutter/Dart crypto plugin backed by ``ccc_rust`` (wolfSSL). All 16 integration tests pass on macOS, iOS, and Android. Windows and Linux platform builds are deferred but do not block app integration — the Dart API is frozen. **The single rule for Milestone 3:** consume the published Dart API only. No Rust changes, no bridge changes, no modifications to the plugin source. Related Documents ~~~~~~~~~~~~~~~~~ * ``docs/ccc_fplugin_phases.rst`` — Milestone 2 phase completion status * ``docs/ccc_fplugin_architecture_design.rst`` — Plugin architecture * ``docs/ccc_fplugin_build_windows.rst`` — Windows build guide (deferred) ---- Open Items (not blocking M3 start) ----------------------------------- The following Milestone 2 tasks are open but do not affect the Dart API: * ``flutter build windows`` / integration tests on Windows — deferred * ``flutter build linux`` / integration tests on Linux — deferred * ``CHANGELOG.md`` not yet updated * ``ccc_rust`` dependency commit not yet pinned to the final ``v0.1.0`` tag * Plugin not yet tagged ``v0.1.0`` These will be resolved in parallel. The app may begin integration against the current commit. When the ``v0.1.0`` tag is cut, update the git ref in the app's ``pubspec.yaml``. ---- Phase Overview -------------- ====== ============================================ ========== ============ Phase Title Status Depends on ====== ============================================ ========== ============ M3-1 Add plugin dependency Not started — M3-2 App startup initialisation Not started M3-1 M3-3 Replace AEAD crypto stubs Not started M3-2 M3-4 Replace KDF stubs Not started M3-2 M3-5 Replace MAC stubs Not started M3-2 M3-6 Replace Hash stubs Not started M3-2 M3-7 Replace KEM stubs Not started M3-2 M3-8 Provider catalog integration Not started M3-2 M3-9 Self-test debug UI Not started M3-2 M3-10 Exception handling audit Not started M3-3–7 M3-11 End-to-end app testing Not started M3-3–9 ====== ============================================ ========== ============ ---- Phase M3-1 — Add Plugin Dependency ------------------------------------ Add the plugin to the LetUsMsg ``pubspec.yaml``:: dependencies: ccc_cryptography: git: url: ssh://git@10.0.5.109/j3g/ccc_fplugin.git ref: main # replace with "v0.1.0" once tagged Then fetch:: flutter pub get .. note:: The plugin is not published to pub.dev. It is consumed as a git dependency. When the ``v0.1.0`` tag is cut, change ``ref: main`` to ``ref: v0.1.0`` and pin the dependency. ---- Phase M3-2 — App Startup Initialisation ----------------------------------------- ``CccCrypto.init()`` must be called **once** at application startup, before any cryptographic operation. It registers the wolfSSL provider and initialises the FRB runtime. It is safe to call multiple times (idempotent), but should be called exactly once in practice. Typical placement is in ``main()`` before ``runApp()``:: import 'package:ccc_cryptography/ccc_cryptography.dart'; Future main() async { WidgetsFlutterBinding.ensureInitialized(); await CccCrypto.init(); runApp(const MyApp()); } Exit criteria: * ``CccCrypto.init()`` called before any crypto operation in the app * No ``CccInternalError`` thrown at startup (provider registered OK) ---- Phase M3-3 — Replace AEAD Crypto Stubs ----------------------------------------- Replace existing encrypt/decrypt stubs with ``CccCrypto.encryptAead`` and ``CccCrypto.decryptAead``. API signatures ~~~~~~~~~~~~~~ .. code-block:: dart // Encrypt — returns ciphertext with authentication tag appended Future CccCrypto.encryptAead({ required CccAeadAlgorithm algorithm, required Uint8List key, required Uint8List nonce, required Uint8List plaintext, Uint8List? aad, // optional associated data; defaults to empty }); // Decrypt — strips and verifies tag internally // Throws CccAuthenticationFailed if tag does not verify Future CccCrypto.decryptAead({ required CccAeadAlgorithm algorithm, required Uint8List key, required Uint8List nonce, required Uint8List ciphertext, // ciphertext + tag as returned by encryptAead Uint8List? aad, }); Algorithm enum and key/nonce sizes ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ========================= ===== ======= ===== ======== ``CccAeadAlgorithm`` ID Key Nonce Tag ========================= ===== ======= ===== ======== ``aesGcm256`` 12 32 B 12 B 16 B ``chaCha20Poly1305`` 13 32 B 12 B 16 B ``xChaCha20Poly1305`` 14 32 B 24 B 16 B ``ascon128a`` 15 16 B 16 B 16 B ========================= ===== ======= ===== ======== .. important:: The returned ciphertext from ``encryptAead`` is ``len(plaintext) + 16 bytes`` (plaintext + 16-byte tag concatenated). Pass the entire slice to ``decryptAead`` — do not strip the tag manually. Example ~~~~~~~ .. code-block:: dart final key = ... // 32 bytes, from KDF or secure RNG final nonce = ... // 12 bytes, non-repeating per (key, message) pair final ciphertext = await CccCrypto.encryptAead( algorithm: CccAeadAlgorithm.aesGcm256, key: key, nonce: nonce, plaintext: message, ); final plaintext = await CccCrypto.decryptAead( algorithm: CccAeadAlgorithm.aesGcm256, key: key, nonce: nonce, ciphertext: ciphertext, // full slice including tag ); ---- Phase M3-4 — Replace KDF Stubs --------------------------------- API signature ~~~~~~~~~~~~~ .. code-block:: dart Future CccCrypto.deriveKey({ required CccKdfAlgorithm algorithm, required Uint8List ikm, // input key material Uint8List? salt, // optional; defaults to empty Uint8List? info, // optional context; defaults to empty required int length, // desired output length in bytes }); Algorithm enum ~~~~~~~~~~~~~~ ========================== ===== ========== ``CccKdfAlgorithm`` ID Notes ========================== ===== ========== ``sha256`` 1 HKDF-SHA256 ``sha384`` 2 HKDF-SHA384 ``sha512`` 3 HKDF-SHA512 ``blake2b512`` 4 BLAKE2b-512 KDF ========================== ===== ========== Example — derive a 32-byte session key via HKDF-SHA256 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ .. code-block:: dart final sessionKey = await CccCrypto.deriveKey( algorithm: CccKdfAlgorithm.sha256, ikm: sharedSecret, salt: sessionSalt, info: Uint8List.fromList(utf8.encode('letusmsg-session-v1')), length: 32, ); ---- Phase M3-5 — Replace MAC Stubs --------------------------------- API signatures ~~~~~~~~~~~~~~ .. code-block:: dart Future CccCrypto.computeMac({ required CccMacAlgorithm algorithm, required Uint8List key, required Uint8List data, }); // Returns true if valid, false otherwise — never throws for tampered data Future CccCrypto.verifyMac({ required CccMacAlgorithm algorithm, required Uint8List key, required Uint8List data, required Uint8List mac, }); Algorithm enum ~~~~~~~~~~~~~~ ======================== ===== ``CccMacAlgorithm`` ID ======================== ===== ``hmacSha256`` 30 ``hmacSha512`` 32 ``blake2bMac`` 33 ======================== ===== .. note:: ``verifyMac`` uses a constant-time comparison in Rust to prevent timing attacks. Do not compare MAC tags in Dart. ---- Phase M3-6 — Replace Hash Stubs ---------------------------------- API signature ~~~~~~~~~~~~~ .. code-block:: dart Future CccCrypto.hash({ required CccHashAlgorithm algorithm, required Uint8List data, }); Algorithm enum ~~~~~~~~~~~~~~ ======================== ===== ``CccHashAlgorithm`` ID ======================== ===== ``sha256`` 40 ``sha384`` 41 ``sha512`` 42 ``blake2b512`` 43 ``sha3_256`` 44 ======================== ===== ---- Phase M3-7 — Replace KEM Stubs --------------------------------- API signatures ~~~~~~~~~~~~~~ .. code-block:: dart // Key generation Future CccCrypto.kemGenerateKeypair({ required CccKemAlgorithm algorithm, }); // CccKemKeyPair { Uint8List publicKey; Uint8List privateKey; } // Encapsulation — sender uses recipient's public key Future CccCrypto.kemEncapsulate({ required CccKemAlgorithm algorithm, required Uint8List publicKey, }); // CccKemEncapResult { Uint8List ciphertext; Uint8List sharedSecret; } // Decapsulation — recipient recovers shared secret Future CccCrypto.kemDecapsulate({ required CccKemAlgorithm algorithm, required Uint8List privateKey, required Uint8List ciphertext, }); Algorithm enum ~~~~~~~~~~~~~~ ========================== ===== ============================== ``CccKemAlgorithm`` ID Notes ========================== ===== ============================== ``x25519`` 50 Available ``x448`` 51 Available ``mlKem768`` 52 Deferred (not compiled in v0.1) ``mlKem1024`` 53 Deferred ``classicMcEliece`` 54 Deferred ========================== ===== ============================== .. warning:: ``privateKey`` in ``CccKemKeyPair`` is Dart-side memory. Discard it as soon as decapsulation is complete. Do not persist or log private keys. ---- Phase M3-8 — Provider Catalog Integration ------------------------------------------- ``CccProviderCatalog`` exposes runtime algorithm availability so the app can adapt its UI and protocol negotiation to what the provider actually supports. API ~~~ .. code-block:: dart // One-shot fetch; cache the result for the session lifetime final catalog = await CccCrypto.getCapabilities(); catalog.providerName // "wolfssl" catalog.aead // List catalog.availableAead // filtered: only available == true catalog.kdf / .availableKdf catalog.mac / .availableMac catalog.hash / .availableHash catalog.kem / .availableKem // CccAlgorithmInfo fields: // int id (matches enum discriminant) // String name (e.g. "AES-256-GCM") // bool available // bool deterministicIo // int efficiencyScore (0–100) // int reliabilityScore (0–100) Also available — synchronous provider list:: final List providers = CccCrypto.listProviders(); // ["wolfssl"] Suggested app usage ~~~~~~~~~~~~~~~~~~~~ * Cache the ``CccProviderCatalog`` in a top-level service singleton after ``CccCrypto.init()``. * Use ``availableAead``, ``availableKem`` etc. to populate algorithm selection UI and protocol negotiation logic. * Use ``efficiencyScore`` / ``reliabilityScore`` to recommend a default algorithm when the user has no preference. ---- Phase M3-9 — Self-Test Debug UI ---------------------------------- Expose ``CccCrypto.runSelfTest()`` in a developer/debug settings screen to give field visibility into provider health. API ~~~ .. code-block:: dart final CccSelfTestResult result = await CccCrypto.runSelfTest(); result.providerName // "wolfssl" result.allPassed // bool — false if any algorithm fails result.results // List result.failures // filtered: only failed results // CccAlgorithmTestResult fields: // int algoId // String algoName // bool passed // String? errorMessage // null on pass Known caveat ~~~~~~~~~~~~ The ``ccc_rust`` AEAD self-test vectors currently miscount the output length (they do not account for the appended 16-byte authentication tag). This causes ``AES-256-GCM`` and ``ChaCha20-Poly1305`` to report failures in the self-test report even though those algorithms work correctly. This is a known upstream bug in ``ccc_rust`` and does not affect production encrypt/decrypt operations. The debug UI should note this when displaying AEAD self-test failures. ---- Phase M3-10 — Exception Handling Audit ----------------------------------------- All ``CccCrypto`` methods throw typed subclasses of ``CccException`` (a ``sealed class``). The full hierarchy: .. code-block:: dart sealed class CccException implements Exception { final String message; } class CccUnsupportedAlgorithm extends CccException { ... } class CccInvalidKey extends CccException { ... } class CccInvalidNonce extends CccException { ... } class CccAuthenticationFailed extends CccException { ... } class CccInvalidInput extends CccException { ... } class CccFeatureNotCompiled extends CccException { ... } class CccInternalError extends CccException { ... } Handling guidelines ~~~~~~~~~~~~~~~~~~~~ * Catch ``CccAuthenticationFailed`` specifically — it is the signal for a tampered or corrupted message. Do not silently discard it. * Catch ``CccUnsupportedAlgorithm`` at the protocol negotiation layer to fall back gracefully. * Catch ``CccInvalidKey`` / ``CccInvalidNonce`` at the key-management layer — these indicate a programming error (wrong buffer size) and should be surfaced in development, not silently swallowed. * ``CccInternalError`` is unexpected; log it and surface a generic "crypto failure" error to the user. Dart 3 exhaustive switch example ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ .. code-block:: dart try { final ct = await CccCrypto.encryptAead(...); } on CccException catch (e) { switch (e) { case CccAuthenticationFailed(): // message tampered case CccInvalidKey(): // bad key — developer error case CccInvalidNonce(): // bad nonce — developer error case CccUnsupportedAlgorithm(): // negotiate fallback case CccFeatureNotCompiled(): // algorithm not built in case CccInvalidInput(): // bad input data case CccInternalError(): // log and surface generic error } } Audit checklist ~~~~~~~~~~~~~~~~ For every call-site that replaces an existing crypto stub, verify: * ``CccAuthenticationFailed`` is caught and handled (not re-thrown as a generic error) * Key / nonce sizes match the table in Phase M3-3 (wrong sizes → ``CccInvalidKey`` / ``CccInvalidNonce``) * No raw ``CccException`` is exposed to end-users — wrap in app-level error types ---- Phase M3-11 — End-to-End App Testing --------------------------------------- Run the existing LetUsMsg integration test suite after all stubs are replaced to confirm no regressions. Additionally verify: * App startup completes with ``CccCrypto.init()`` — no crash or timeout * Encrypt → transmit → decrypt roundtrip succeeds on iOS, Android, macOS * Provider catalog loads and populates the settings UI correctly * Self-test screen shows expected results (note AEAD caveat above) * No ``CccException`` surfaces to end-users under normal operation * Private key material is not logged or persisted anywhere in the app ---- Hard Boundaries for Milestone 3 --------------------------------- The following are **forbidden** during app integration: * Modifying any file in the ``ccc_cryptography`` plugin repository * Implementing cryptographic logic in Dart * Calling ``ccc_rust`` or ``flutter_rust_bridge`` APIs directly * Depending on internal generated files (e.g. ``src/rust/api/crypto.dart``, ``frb_generated.dart``) * Persisting or logging raw private keys (``CccKemKeyPair.privateKey``) The app must depend **only** on the public barrel export:: import 'package:ccc_cryptography/ccc_cryptography.dart'; ---- Algorithm ID Quick Reference ------------------------------ These IDs match the ``cipher_constants.dart`` integer constants in the existing app exactly — no translation layer is needed. ========================= ===== ============================ Algorithm ID Category ========================= ===== ============================ ``aesGcm256`` 12 AEAD ``chaCha20Poly1305`` 13 AEAD ``xChaCha20Poly1305`` 14 AEAD ``ascon128a`` 15 AEAD ``sha256`` (KDF) 1 KDF (HKDF-SHA256) ``sha384`` (KDF) 2 KDF (HKDF-SHA384) ``sha512`` (KDF) 3 KDF (HKDF-SHA512) ``blake2b512`` (KDF) 4 KDF ``hmacSha256`` 30 MAC ``hmacSha512`` 32 MAC ``blake2bMac`` 33 MAC ``sha256`` (Hash) 40 Hash ``sha384`` (Hash) 41 Hash ``sha512`` (Hash) 42 Hash ``blake2b512`` (Hash) 43 Hash ``sha3_256`` 44 Hash ``x25519`` 50 KEM ``x448`` 51 KEM ``mlKem768`` 52 KEM (deferred) ``mlKem1024`` 53 KEM (deferred) ``classicMcEliece`` 54 KEM (deferred) ========================= ===== ============================ ---- Milestone 3 Completion Gate ---------------------------- *All items must be checked before Milestone 3 is considered complete.* * ``[ ]`` Plugin added to LetUsMsg ``pubspec.yaml`` * ``[ ]`` ``CccCrypto.init()`` called at app startup * ``[ ]`` All AEAD crypto stubs replaced (Phase M3-3) * ``[ ]`` All KDF stubs replaced (Phase M3-4) * ``[ ]`` All MAC stubs replaced (Phase M3-5) * ``[ ]`` All Hash stubs replaced (Phase M3-6) * ``[ ]`` All KEM stubs replaced (Phase M3-7) * ``[ ]`` Provider catalog surface integrated (Phase M3-8) * ``[ ]`` Self-test debug UI surface integrated (Phase M3-9) * ``[ ]`` Exception handling audit complete (Phase M3-10) * ``[ ]`` End-to-end app tests pass on iOS, Android, macOS (Phase M3-11) * ``[ ]`` No raw private keys exposed, logged, or persisted * ``[ ]`` Plugin dep pinned to ``v0.1.0`` git tag (when cut)