lum_ccc_fplugin/docs/ccc_rust_app_integration_ph...

594 lines
18 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 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-37
M3-11 End-to-end app testing Not started M3-39
====== ============================================ ========== ============
----
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<void> 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<Uint8List> 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<Uint8List> 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<Uint8List> 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<Uint8List> CccCrypto.computeMac({
required CccMacAlgorithm algorithm,
required Uint8List key,
required Uint8List data,
});
// Returns true if valid, false otherwise — never throws for tampered data
Future<bool> 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<Uint8List> 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<CccKemKeyPair> CccCrypto.kemGenerateKeypair({
required CccKemAlgorithm algorithm,
});
// CccKemKeyPair { Uint8List publicKey; Uint8List privateKey; }
// Encapsulation — sender uses recipient's public key
Future<CccKemEncapResult> CccCrypto.kemEncapsulate({
required CccKemAlgorithm algorithm,
required Uint8List publicKey,
});
// CccKemEncapResult { Uint8List ciphertext; Uint8List sharedSecret; }
// Decapsulation — recipient recovers shared secret
Future<Uint8List> 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<CccAlgorithmInfo>
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 (0100)
// int reliabilityScore (0100)
Also available — synchronous provider list::
final List<String> 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<CccAlgorithmTestResult>
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)