From db897b5abe771d403afced7b3f65a3dbe42fe2e0 Mon Sep 17 00:00:00 2001 From: JohnE Date: Tue, 24 Feb 2026 18:47:25 -0800 Subject: [PATCH] MOD: decupple this rust project from dart --- Cargo.lock | 524 +------ Cargo.toml | 1 - crates/ccc-flutter-bridge/.gitignore | 1 - crates/ccc-flutter-bridge/Cargo.lock | 655 -------- crates/ccc-flutter-bridge/Cargo.toml | 28 - .../ccc-flutter-bridge/include/ccc_bridge.h | 1 - crates/ccc-flutter-bridge/src/api/mod.rs | 1 - crates/ccc-flutter-bridge/src/api/simple.rs | 10 - crates/ccc-flutter-bridge/src/bridge.rs | 281 ---- crates/ccc-flutter-bridge/src/dto.rs | 296 ---- .../ccc-flutter-bridge/src/frb_generated.rs | 1354 ----------------- crates/ccc-flutter-bridge/src/lib.rs | 22 - docs/ccc_rust_plan.rst | 374 ++--- docs/ccc_rust_plan_phases.rst | 333 ++-- flutter_rust_bridge.yaml | 24 - .../ccc/attachment_crypto_context.dart | 17 - flutter_src/ccc/ccc_channel_profile.dart | 321 ---- flutter_src/ccc/ccc_iso.dart | 632 -------- flutter_src/ccc/ccc_iso_manager.dart | 247 --- flutter_src/ccc/ccc_iso_operation.dart | 190 --- flutter_src/ccc/ccc_iso_operation_id.dart | 96 -- flutter_src/ccc/ccc_iso_result.dart | 220 --- flutter_src/ccc/ccc_kdf.dart | 40 - flutter_src/ccc/ccc_key_schedule.dart | 148 -- flutter_src/ccc/ccc_provider_spec.dart | 182 --- flutter_src/ccc/cipher_constants.dart | 209 --- flutter_src/ccc/copious_cipher_chain.dart | 116 -- flutter_src/ccc/crypto_abstract.dart | 69 - flutter_src/ccc/crypto_ccc.dart | 81 - flutter_src/ccc/crypto_plaintext.dart | 13 - flutter_src/ccc/crypto_wolfssl.dart | 26 - flutter_src/ccc/enc_dec_json.dart | 43 - flutter_src/ccc/ratchet_engine.dart | 497 ------ flutter_src/ccc/ratchet_state_manager.dart | 154 -- 34 files changed, 269 insertions(+), 6937 deletions(-) delete mode 100644 crates/ccc-flutter-bridge/.gitignore delete mode 100644 crates/ccc-flutter-bridge/Cargo.lock delete mode 100644 crates/ccc-flutter-bridge/Cargo.toml delete mode 100644 crates/ccc-flutter-bridge/include/ccc_bridge.h delete mode 100644 crates/ccc-flutter-bridge/src/api/mod.rs delete mode 100644 crates/ccc-flutter-bridge/src/api/simple.rs delete mode 100644 crates/ccc-flutter-bridge/src/bridge.rs delete mode 100644 crates/ccc-flutter-bridge/src/dto.rs delete mode 100644 crates/ccc-flutter-bridge/src/frb_generated.rs delete mode 100644 crates/ccc-flutter-bridge/src/lib.rs delete mode 100644 flutter_rust_bridge.yaml delete mode 100644 flutter_src/ccc/attachment_crypto_context.dart delete mode 100644 flutter_src/ccc/ccc_channel_profile.dart delete mode 100644 flutter_src/ccc/ccc_iso.dart delete mode 100644 flutter_src/ccc/ccc_iso_manager.dart delete mode 100644 flutter_src/ccc/ccc_iso_operation.dart delete mode 100644 flutter_src/ccc/ccc_iso_operation_id.dart delete mode 100644 flutter_src/ccc/ccc_iso_result.dart delete mode 100644 flutter_src/ccc/ccc_kdf.dart delete mode 100644 flutter_src/ccc/ccc_key_schedule.dart delete mode 100644 flutter_src/ccc/ccc_provider_spec.dart delete mode 100644 flutter_src/ccc/cipher_constants.dart delete mode 100644 flutter_src/ccc/copious_cipher_chain.dart delete mode 100644 flutter_src/ccc/crypto_abstract.dart delete mode 100644 flutter_src/ccc/crypto_ccc.dart delete mode 100644 flutter_src/ccc/crypto_plaintext.dart delete mode 100644 flutter_src/ccc/crypto_wolfssl.dart delete mode 100644 flutter_src/ccc/enc_dec_json.dart delete mode 100644 flutter_src/ccc/ratchet_engine.dart delete mode 100644 flutter_src/ccc/ratchet_state_manager.dart diff --git a/Cargo.lock b/Cargo.lock index 28c2cc2..c639e9e 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2,21 +2,6 @@ # It is not intended for manual editing. version = 4 -[[package]] -name = "addr2line" -version = "0.25.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1b5d307320b3181d6d7954e663bd7c774a838b8220fe0593c86d9fb09f498b4b" -dependencies = [ - "gimli", -] - -[[package]] -name = "adler2" -version = "2.0.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "320119579fcad9c21884f5c4861d16174d0e06250625266f50fe6898340abefa" - [[package]] name = "aho-corasick" version = "1.1.4" @@ -26,34 +11,6 @@ dependencies = [ "memchr", ] -[[package]] -name = "allo-isolate" -version = "0.1.27" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "449e356a4864c017286dbbec0e12767ea07efba29e3b7d984194c2a7ff3c4550" -dependencies = [ - "anyhow", - "atomic", - "backtrace", -] - -[[package]] -name = "android_log-sys" -version = "0.3.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "84521a3cf562bc62942e294181d9eef17eb38ceb8c68677bc49f144e4c3d4f8d" - -[[package]] -name = "android_logger" -version = "0.15.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dbb4e440d04be07da1f1bf44fb4495ebd58669372fe0cffa6e48595ac5bd88a3" -dependencies = [ - "android_log-sys", - "env_filter 0.1.4", - "log", -] - [[package]] name = "anstream" version = "0.6.21" @@ -123,27 +80,6 @@ dependencies = [ "zeroize", ] -[[package]] -name = "atomic" -version = "0.5.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c59bdb34bc650a32731b31bd8f0829cc15d24a708ee31559e0bb34f2bc320cba" - -[[package]] -name = "backtrace" -version = "0.3.76" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bb531853791a215d7c62a30daf0dde835f381ab5de4589cfe7c649d2cbe92bd6" -dependencies = [ - "addr2line", - "cfg-if", - "libc", - "miniz_oxide", - "object", - "rustc-demangle", - "windows-link", -] - [[package]] name = "base64ct" version = "1.8.3" @@ -194,30 +130,6 @@ dependencies = [ "generic-array", ] -[[package]] -name = "build-target" -version = "0.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "832133bbabbbaa9fbdba793456a2827627a7d2b8fb96032fa1e7666d7895832b" - -[[package]] -name = "bumpalo" -version = "3.20.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5d20789868f4b01b2f2caec9f5c4e0213b41e3e5702a50157d699ae31ced2fcb" - -[[package]] -name = "bytemuck" -version = "1.25.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c8efb64bd706a16a1bdde310ae86b351e4d21550d98d056f22f8a7f7a2183fec" - -[[package]] -name = "byteorder" -version = "1.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1fd0f2584146f6f2ef48085050886acf353beff7305ebd1ae69500e27c67f64b" - [[package]] name = "cc" version = "1.2.56" @@ -266,20 +178,6 @@ dependencies = [ "zeroize", ] -[[package]] -name = "ccc-flutter-bridge" -version = "0.1.0" -dependencies = [ - "anyhow", - "ccc-crypto-core", - "ccc-crypto-wolfssl", - "env_logger", - "flutter_rust_bridge", - "hex", - "log", - "zeroize", -] - [[package]] name = "cexpr" version = "0.6.0" @@ -321,16 +219,6 @@ version = "1.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b05b61dc5112cbb17e4b6cd61790d9845d13888356391624cbe7e41efeac1e75" -[[package]] -name = "console_error_panic_hook" -version = "0.1.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a06aeb73f470f66dcdbf7223caeebb85984942f22f1adb2a088cf9668146bbbc" -dependencies = [ - "cfg-if", - "wasm-bindgen", -] - [[package]] name = "cpufeatures" version = "0.2.17" @@ -350,39 +238,6 @@ dependencies = [ "typenum", ] -[[package]] -name = "dart-sys" -version = "4.1.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "57967e4b200d767d091b961d6ab42cc7d0cc14fe9e052e75d0d3cf9eb732d895" -dependencies = [ - "cc", -] - -[[package]] -name = "dashmap" -version = "5.5.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "978747c1d849a7d2ee5e8adc0159961c48fb7e5db2f06af6723b80123bb53856" -dependencies = [ - "cfg-if", - "hashbrown", - "lock_api", - "once_cell", - "parking_lot_core", -] - -[[package]] -name = "delegate-attr" -version = "0.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "51aac4c99b2e6775164b412ea33ae8441b2fde2dbf05a20bc0052a63d08c475b" -dependencies = [ - "proc-macro2", - "quote", - "syn", -] - [[package]] name = "digest" version = "0.10.7" @@ -400,16 +255,6 @@ version = "1.15.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "48c757948c5ede0e46177b7add2e67155f70e33c07fea8284df6576da70b3719" -[[package]] -name = "env_filter" -version = "0.1.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1bf3c259d255ca70051b30e2e95b5446cdb8949ac4cd22c0d7fd634d89f568e2" -dependencies = [ - "log", - "regex", -] - [[package]] name = "env_filter" version = "1.0.0" @@ -428,7 +273,7 @@ checksum = "b2daee4ea451f429a58296525ddf28b45a3b64f1acf6587e2067437bb11e218d" dependencies = [ "anstream", "anstyle", - "env_filter 1.0.0", + "env_filter", "jiff", "log", ] @@ -439,136 +284,6 @@ version = "0.1.9" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5baebc0774151f905a1a2cc41989300b1e6fbb29aff0ceffa1064fdd3088d582" -[[package]] -name = "flutter_rust_bridge" -version = "2.11.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dde126295b2acc5f0a712e265e91b6fdc0ed38767496483e592ae7134db83725" -dependencies = [ - "allo-isolate", - "android_logger", - "anyhow", - "build-target", - "bytemuck", - "byteorder", - "console_error_panic_hook", - "dart-sys", - "delegate-attr", - "flutter_rust_bridge_macros", - "futures", - "js-sys", - "lazy_static", - "log", - "oslog", - "portable-atomic", - "threadpool", - "tokio", - "wasm-bindgen", - "wasm-bindgen-futures", - "web-sys", -] - -[[package]] -name = "flutter_rust_bridge_macros" -version = "2.11.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d5f0420326b13675321b194928bb7830043b68cf8b810e1c651285c747abb080" -dependencies = [ - "hex", - "md-5", - "proc-macro2", - "quote", - "syn", -] - -[[package]] -name = "futures" -version = "0.3.32" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8b147ee9d1f6d097cef9ce628cd2ee62288d963e16fb287bd9286455b241382d" -dependencies = [ - "futures-channel", - "futures-core", - "futures-executor", - "futures-io", - "futures-sink", - "futures-task", - "futures-util", -] - -[[package]] -name = "futures-channel" -version = "0.3.32" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "07bbe89c50d7a535e539b8c17bc0b49bdb77747034daa8087407d655f3f7cc1d" -dependencies = [ - "futures-core", - "futures-sink", -] - -[[package]] -name = "futures-core" -version = "0.3.32" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7e3450815272ef58cec6d564423f6e755e25379b217b0bc688e295ba24df6b1d" - -[[package]] -name = "futures-executor" -version = "0.3.32" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "baf29c38818342a3b26b5b923639e7b1f4a61fc5e76102d4b1981c6dc7a7579d" -dependencies = [ - "futures-core", - "futures-task", - "futures-util", -] - -[[package]] -name = "futures-io" -version = "0.3.32" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cecba35d7ad927e23624b22ad55235f2239cfa44fd10428eecbeba6d6a717718" - -[[package]] -name = "futures-macro" -version = "0.3.32" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e835b70203e41293343137df5c0664546da5745f82ec9b84d40be8336958447b" -dependencies = [ - "proc-macro2", - "quote", - "syn", -] - -[[package]] -name = "futures-sink" -version = "0.3.32" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c39754e157331b013978ec91992bde1ac089843443c49cbc7f46150b0fad0893" - -[[package]] -name = "futures-task" -version = "0.3.32" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "037711b3d59c33004d3856fbdc83b99d4ff37a24768fa1be9ce3538a1cde4393" - -[[package]] -name = "futures-util" -version = "0.3.32" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "389ca41296e6190b48053de0321d02a77f32f8a5d2461dd38762c0593805c6d6" -dependencies = [ - "futures-channel", - "futures-core", - "futures-io", - "futures-macro", - "futures-sink", - "futures-task", - "memchr", - "pin-project-lite", - "slab", -] - [[package]] name = "generic-array" version = "0.14.7" @@ -579,30 +294,12 @@ dependencies = [ "version_check", ] -[[package]] -name = "gimli" -version = "0.32.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e629b9b98ef3dd8afe6ca2bd0f89306cec16d43d907889945bc5d6687f2f13c7" - [[package]] name = "glob" version = "0.3.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0cc23270f6e1808e30a928bdc84dea0b9b4136a8bc82338574f23baf47bbd280" -[[package]] -name = "hashbrown" -version = "0.14.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e5274423e17b7c9fc20b6e7e208532f9b19825d82dfd615708b70edd83df41f1" - -[[package]] -name = "hermit-abi" -version = "0.5.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fc0fef456e4baa96da950455cd02c081ca953b141298e41db3fc7e36b1da849c" - [[package]] name = "hex" version = "0.4.3" @@ -654,22 +351,6 @@ dependencies = [ "syn", ] -[[package]] -name = "js-sys" -version = "0.3.88" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c7e709f3e3d22866f9c25b3aff01af289b18422cc8b4262fb19103ee80fe513d" -dependencies = [ - "once_cell", - "wasm-bindgen", -] - -[[package]] -name = "lazy_static" -version = "1.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bbd2bcb4c963f2ddae06a2efc7e9f3591312473c50c6685e1f298068316e66fe" - [[package]] name = "libc" version = "0.2.182" @@ -686,31 +367,12 @@ dependencies = [ "windows-link", ] -[[package]] -name = "lock_api" -version = "0.4.14" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "224399e74b87b5f3557511d98dff8b14089b3dadafcab6bb93eab67d3aace965" -dependencies = [ - "scopeguard", -] - [[package]] name = "log" version = "0.4.29" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5e5032e24019045c762d3c0f28f5b6b8bbf38563a65908389bf7978758920897" -[[package]] -name = "md-5" -version = "0.10.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d89e7ee0cfbedfc4da3340218492196241d89eefb6dab27de5df917a6d2e78cf" -dependencies = [ - "cfg-if", - "digest", -] - [[package]] name = "memchr" version = "2.8.0" @@ -723,15 +385,6 @@ version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "68354c5c6bd36d73ff3feceb05efa59b6acb7626617f4962be322a825e61f79a" -[[package]] -name = "miniz_oxide" -version = "0.8.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1fa76a2c86f704bdb222d66965fb3d63269ce38518b83cb0575fca855ebb6316" -dependencies = [ - "adler2", -] - [[package]] name = "nom" version = "7.1.3" @@ -742,25 +395,6 @@ dependencies = [ "minimal-lexical", ] -[[package]] -name = "num_cpus" -version = "1.17.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "91df4bbde75afed763b708b7eee1e8e7651e02d97f6d5dd763e89367e957b23b" -dependencies = [ - "hermit-abi", - "libc", -] - -[[package]] -name = "object" -version = "0.37.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ff76201f031d8863c38aa7f905eca4f53abbfa15f609db4277d44cd8938f33fe" -dependencies = [ - "memchr", -] - [[package]] name = "once_cell" version = "1.21.3" @@ -773,30 +407,6 @@ version = "1.70.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "384b8ab6d37215f3c5301a95a4accb5d64aa607f1fcb26a11b5303878451b4fe" -[[package]] -name = "oslog" -version = "0.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "80d2043d1f61d77cb2f4b1f7b7b2295f40507f5f8e9d1c8bf10a1ca5f97a3969" -dependencies = [ - "cc", - "dashmap", - "log", -] - -[[package]] -name = "parking_lot_core" -version = "0.9.12" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2621685985a2ebf1c516881c026032ac7deafcda1a2c9b7850dc81e3dfcb64c1" -dependencies = [ - "cfg-if", - "libc", - "redox_syscall", - "smallvec", - "windows-link", -] - [[package]] name = "password-hash" version = "0.5.0" @@ -808,12 +418,6 @@ dependencies = [ "subtle", ] -[[package]] -name = "pin-project-lite" -version = "0.2.16" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3b3cff922bd51709b605d9ead9aa71031d81447142d828eb4a6eba76fe619f9b" - [[package]] name = "portable-atomic" version = "1.13.1" @@ -863,15 +467,6 @@ version = "0.6.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c" -[[package]] -name = "redox_syscall" -version = "0.5.18" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ed2bf2547551a7053d6fdfafda3f938979645c44812fbfcda098faae3f1a362d" -dependencies = [ - "bitflags", -] - [[package]] name = "regex" version = "1.12.3" @@ -901,30 +496,12 @@ version = "0.8.9" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a96887878f22d7bad8a3b6dc5b7440e0ada9a245242924394987b21cf2210a4c" -[[package]] -name = "rustc-demangle" -version = "0.1.27" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b50b8869d9fc858ce7266cce0194bd74df58b9d0e3f6df3a9fc8eb470d95c09d" - [[package]] name = "rustc-hash" version = "2.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "357703d41365b4b27c590e3ed91eabb1b663f07c4c084095e60cbed4362dff0d" -[[package]] -name = "rustversion" -version = "1.0.22" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b39cdef0fa800fc44525c84ccb54a029961a8215f9619753635a9c0d2538d46d" - -[[package]] -name = "scopeguard" -version = "1.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49" - [[package]] name = "serde" version = "1.0.228" @@ -974,18 +551,6 @@ version = "1.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0fda2ff0d084019ba4d7c6f371c95d8fd75ce3524c3cb8fb653a3023f6323e64" -[[package]] -name = "slab" -version = "0.4.12" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0c790de23124f9ab44544d7ac05d60440adc586479ce501c1d6d7da3cd8c9cf5" - -[[package]] -name = "smallvec" -version = "1.15.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "67b1b7a3b5fe4f1376887184045fcf45c69e92af734b7aaddc05fb777b6fbd03" - [[package]] name = "subtle" version = "2.6.1" @@ -1023,24 +588,6 @@ dependencies = [ "syn", ] -[[package]] -name = "threadpool" -version = "1.8.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d050e60b33d41c19108b32cea32164033a9013fe3b46cbd4457559bfbf77afaa" -dependencies = [ - "num_cpus", -] - -[[package]] -name = "tokio" -version = "1.49.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "72a2903cd7736441aac9df9d7688bd0ce48edccaadf181c3b90be801e81d3d86" -dependencies = [ - "pin-project-lite", -] - [[package]] name = "typenum" version = "1.19.0" @@ -1065,75 +612,6 @@ version = "0.9.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0b928f33d975fc6ad9f86c8f283853ad26bdd5b10b7f1542aa2fa15e2289105a" -[[package]] -name = "wasm-bindgen" -version = "0.2.111" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ec1adf1535672f5b7824f817792b1afd731d7e843d2d04ec8f27e8cb51edd8ac" -dependencies = [ - "cfg-if", - "once_cell", - "rustversion", - "wasm-bindgen-macro", - "wasm-bindgen-shared", -] - -[[package]] -name = "wasm-bindgen-futures" -version = "0.4.61" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fe88540d1c934c4ec8e6db0afa536876c5441289d7f9f9123d4f065ac1250a6b" -dependencies = [ - "cfg-if", - "futures-util", - "js-sys", - "once_cell", - "wasm-bindgen", - "web-sys", -] - -[[package]] -name = "wasm-bindgen-macro" -version = "0.2.111" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "19e638317c08b21663aed4d2b9a2091450548954695ff4efa75bff5fa546b3b1" -dependencies = [ - "quote", - "wasm-bindgen-macro-support", -] - -[[package]] -name = "wasm-bindgen-macro-support" -version = "0.2.111" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2c64760850114d03d5f65457e96fc988f11f01d38fbaa51b254e4ab5809102af" -dependencies = [ - "bumpalo", - "proc-macro2", - "quote", - "syn", - "wasm-bindgen-shared", -] - -[[package]] -name = "wasm-bindgen-shared" -version = "0.2.111" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "60eecd4fe26177cfa3339eb00b4a36445889ba3ad37080c2429879718e20ca41" -dependencies = [ - "unicode-ident", -] - -[[package]] -name = "web-sys" -version = "0.3.88" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9d6bb20ed2d9572df8584f6dc81d68a41a625cadc6f15999d649a70ce7e3597a" -dependencies = [ - "js-sys", - "wasm-bindgen", -] - [[package]] name = "windows-link" version = "0.2.1" diff --git a/Cargo.toml b/Cargo.toml index cbb0770..239bf0b 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -3,7 +3,6 @@ resolver = "2" members = [ "crates/ccc-crypto-core", "crates/ccc-crypto-wolfssl", - "crates/ccc-flutter-bridge", "tests/conformance", ] diff --git a/crates/ccc-flutter-bridge/.gitignore b/crates/ccc-flutter-bridge/.gitignore deleted file mode 100644 index ea8c4bf..0000000 --- a/crates/ccc-flutter-bridge/.gitignore +++ /dev/null @@ -1 +0,0 @@ -/target diff --git a/crates/ccc-flutter-bridge/Cargo.lock b/crates/ccc-flutter-bridge/Cargo.lock deleted file mode 100644 index 185e862..0000000 --- a/crates/ccc-flutter-bridge/Cargo.lock +++ /dev/null @@ -1,655 +0,0 @@ -# This file is automatically @generated by Cargo. -# It is not intended for manual editing. -version = 3 - -[[package]] -name = "addr2line" -version = "0.21.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8a30b2e23b9e17a9f90641c7ab1549cd9b44f296d3ccbf309d2863cfe398a0cb" -dependencies = [ - "gimli", -] - -[[package]] -name = "adler" -version = "1.0.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f26201604c87b1e01bd3d98f8d5d9a8fcbb815e8cedb41ffccbeb4bf593a35fe" - -[[package]] -name = "aho-corasick" -version = "1.1.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b2969dcb958b36655471fc61f7e416fa76033bdd4bfed0678d8fee1e2d07a1f0" -dependencies = [ - "memchr", -] - -[[package]] -name = "allo-isolate" -version = "0.1.25" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "97b6d794345b06592d0ebeed8e477e41b71e5a0a49df4fc0e4184d5938b99509" -dependencies = [ - "anyhow", - "atomic", - "backtrace", -] - -[[package]] -name = "android_log-sys" -version = "0.3.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5ecc8056bf6ab9892dcd53216c83d1597487d7dacac16c8df6b877d127df9937" - -[[package]] -name = "android_logger" -version = "0.13.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c494134f746c14dc653a35a4ea5aca24ac368529da5370ecf41fe0341c35772f" -dependencies = [ - "android_log-sys", - "env_logger", - "log", - "once_cell", -] - -[[package]] -name = "anyhow" -version = "1.0.75" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a4668cab20f66d8d020e1fbc0ebe47217433c1b6c8f2040faf858554e394ace6" - -[[package]] -name = "atomic" -version = "0.5.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c59bdb34bc650a32731b31bd8f0829cc15d24a708ee31559e0bb34f2bc320cba" - -[[package]] -name = "autocfg" -version = "1.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa" - -[[package]] -name = "backtrace" -version = "0.3.69" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2089b7e3f35b9dd2d0ed921ead4f6d318c27680d4a5bd167b3ee120edb105837" -dependencies = [ - "addr2line", - "cc", - "cfg-if", - "libc", - "miniz_oxide", - "object", - "rustc-demangle", -] - -[[package]] -name = "block-buffer" -version = "0.10.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3078c7629b62d3f0439517fa394996acacc5cbc91c5a20d8c658e77abd503a71" -dependencies = [ - "generic-array", -] - -[[package]] -name = "build-target" -version = "0.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "832133bbabbbaa9fbdba793456a2827627a7d2b8fb96032fa1e7666d7895832b" - -[[package]] -name = "bumpalo" -version = "3.14.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7f30e7476521f6f8af1a1c4c0b8cc94f0bee37d91763d0ca2665f299b6cd8aec" - -[[package]] -name = "bytemuck" -version = "1.14.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "374d28ec25809ee0e23827c2ab573d729e293f281dfe393500e7ad618baa61c6" - -[[package]] -name = "byteorder" -version = "1.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1fd0f2584146f6f2ef48085050886acf353beff7305ebd1ae69500e27c67f64b" - -[[package]] -name = "cc" -version = "1.0.83" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f1174fb0b6ec23863f8b971027804a42614e347eafb0a95bf0b12cdae21fc4d0" -dependencies = [ - "libc", -] - -[[package]] -name = "cfg-if" -version = "1.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" - -[[package]] -name = "console_error_panic_hook" -version = "0.1.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a06aeb73f470f66dcdbf7223caeebb85984942f22f1adb2a088cf9668146bbbc" -dependencies = [ - "cfg-if", - "wasm-bindgen", -] - -[[package]] -name = "crypto-common" -version = "0.1.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1bfb12502f3fc46cca1bb51ac28df9d618d813cdc3d2f25b9fe775a34af26bb3" -dependencies = [ - "generic-array", - "typenum", -] - -[[package]] -name = "dart-sys-fork" -version = "4.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "933dafff26172b719bb9695dd3715a1e7792f62dcdc8a5d4c740db7e0fedee8b" -dependencies = [ - "cc", -] - -[[package]] -name = "dashmap" -version = "4.0.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e77a43b28d0668df09411cb0bc9a8c2adc40f9a048afe863e05fd43251e8e39c" -dependencies = [ - "cfg-if", - "num_cpus", -] - -[[package]] -name = "delegate-attr" -version = "0.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "51aac4c99b2e6775164b412ea33ae8441b2fde2dbf05a20bc0052a63d08c475b" -dependencies = [ - "proc-macro2", - "quote", - "syn", -] - -[[package]] -name = "digest" -version = "0.10.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9ed9a281f7bc9b7576e61468ba615a66a5c8cfdff42420a70aa82701a3b1e292" -dependencies = [ - "block-buffer", - "crypto-common", -] - -[[package]] -name = "env_logger" -version = "0.10.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "95b3f3e67048839cb0d0781f445682a35113da7121f7c949db0e2be96a4fbece" -dependencies = [ - "log", - "regex", -] - -[[package]] -name = "flutter_rust_bridge" -version = "2.11.1" -dependencies = [ - "allo-isolate", - "android_logger", - "anyhow", - "build-target", - "bytemuck", - "byteorder", - "console_error_panic_hook", - "dart-sys-fork", - "delegate-attr", - "flutter_rust_bridge_macros", - "futures", - "js-sys", - "lazy_static", - "log", - "oslog", - "threadpool", - "tokio", - "wasm-bindgen", - "wasm-bindgen-futures", - "web-sys", -] - -[[package]] -name = "flutter_rust_bridge_macros" -version = "2.11.1" -dependencies = [ - "hex", - "md-5", - "proc-macro2", - "quote", - "syn", -] - -[[package]] -name = "futures" -version = "0.3.29" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "da0290714b38af9b4a7b094b8a37086d1b4e61f2df9122c3cad2577669145335" -dependencies = [ - "futures-channel", - "futures-core", - "futures-executor", - "futures-io", - "futures-sink", - "futures-task", - "futures-util", -] - -[[package]] -name = "futures-channel" -version = "0.3.29" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ff4dd66668b557604244583e3e1e1eada8c5c2e96a6d0d6653ede395b78bbacb" -dependencies = [ - "futures-core", - "futures-sink", -] - -[[package]] -name = "futures-core" -version = "0.3.29" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "eb1d22c66e66d9d72e1758f0bd7d4fd0bee04cad842ee34587d68c07e45d088c" - -[[package]] -name = "futures-executor" -version = "0.3.29" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0f4fb8693db0cf099eadcca0efe2a5a22e4550f98ed16aba6c48700da29597bc" -dependencies = [ - "futures-core", - "futures-task", - "futures-util", -] - -[[package]] -name = "futures-io" -version = "0.3.29" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8bf34a163b5c4c52d0478a4d757da8fb65cabef42ba90515efee0f6f9fa45aaa" - -[[package]] -name = "futures-macro" -version = "0.3.29" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "53b153fd91e4b0147f4aced87be237c98248656bb01050b96bf3ee89220a8ddb" -dependencies = [ - "proc-macro2", - "quote", - "syn", -] - -[[package]] -name = "futures-sink" -version = "0.3.29" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e36d3378ee38c2a36ad710c5d30c2911d752cb941c00c72dbabfb786a7970817" - -[[package]] -name = "futures-task" -version = "0.3.29" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "efd193069b0ddadc69c46389b740bbccdd97203899b48d09c5f7969591d6bae2" - -[[package]] -name = "futures-util" -version = "0.3.29" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a19526d624e703a3179b3d322efec918b6246ea0fa51d41124525f00f1cc8104" -dependencies = [ - "futures-channel", - "futures-core", - "futures-io", - "futures-macro", - "futures-sink", - "futures-task", - "memchr", - "pin-project-lite", - "pin-utils", - "slab", -] - -[[package]] -name = "generic-array" -version = "0.14.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "85649ca51fd72272d7821adaf274ad91c288277713d9c18820d8499a7ff69e9a" -dependencies = [ - "typenum", - "version_check", -] - -[[package]] -name = "gimli" -version = "0.28.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4271d37baee1b8c7e4b708028c57d816cf9d2434acb33a549475f78c181f6253" - -[[package]] -name = "hermit-abi" -version = "0.3.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d77f7ec81a6d05a3abb01ab6eb7590f6083d08449fe5a1c8b1e620283546ccb7" - -[[package]] -name = "hex" -version = "0.4.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7f24254aa9a54b5c858eaee2f5bccdb46aaf0e486a595ed5fd8f86ba55232a70" - -[[package]] -name = "js-sys" -version = "0.3.69" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "29c15563dc2726973df627357ce0c9ddddbea194836909d655df6a75d2cf296d" -dependencies = [ - "wasm-bindgen", -] - -[[package]] -name = "lazy_static" -version = "1.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646" - -[[package]] -name = "libc" -version = "0.2.150" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "89d92a4743f9a61002fae18374ed11e7973f530cb3a3255fb354818118b2203c" - -[[package]] -name = "log" -version = "0.4.20" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b5e6163cb8c49088c2c36f57875e58ccd8c87c7427f7fbd50ea6710b2f3f2e8f" - -[[package]] -name = "md-5" -version = "0.10.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d89e7ee0cfbedfc4da3340218492196241d89eefb6dab27de5df917a6d2e78cf" -dependencies = [ - "cfg-if", - "digest", -] - -[[package]] -name = "memchr" -version = "2.6.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f665ee40bc4a3c5590afb1e9677db74a508659dfd71e126420da8274909a0167" - -[[package]] -name = "miniz_oxide" -version = "0.7.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e7810e0be55b428ada41041c41f32c9f1a42817901b4ccf45fa3d4b6561e74c7" -dependencies = [ - "adler", -] - -[[package]] -name = "num_cpus" -version = "1.16.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4161fcb6d602d4d2081af7c3a45852d875a03dd337a6bfdd6e06407b61342a43" -dependencies = [ - "hermit-abi", - "libc", -] - -[[package]] -name = "object" -version = "0.32.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9cf5f9dd3933bd50a9e1f149ec995f39ae2c496d31fd772c1fd45ebc27e902b0" -dependencies = [ - "memchr", -] - -[[package]] -name = "once_cell" -version = "1.18.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dd8b5dd2ae5ed71462c540258bedcb51965123ad7e7ccf4b9a8cafaa4a63576d" - -[[package]] -name = "oslog" -version = "0.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8343ce955f18e7e68c0207dd0ea776ec453035685395ababd2ea651c569728b3" -dependencies = [ - "cc", - "dashmap", - "log", -] - -[[package]] -name = "pin-project-lite" -version = "0.2.13" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8afb450f006bf6385ca15ef45d71d2288452bc3683ce2e2cacc0d18e4be60b58" - -[[package]] -name = "pin-utils" -version = "0.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184" - -[[package]] -name = "proc-macro2" -version = "1.0.70" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "39278fbbf5fb4f646ce651690877f89d1c5811a3d4acb27700c1cb3cdb78fd3b" -dependencies = [ - "unicode-ident", -] - -[[package]] -name = "quote" -version = "1.0.33" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5267fca4496028628a95160fc423a33e8b2e6af8a5302579e322e4b520293cae" -dependencies = [ - "proc-macro2", -] - -[[package]] -name = "regex" -version = "1.10.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "380b951a9c5e80ddfd6136919eef32310721aa4aacd4889a8d39124b026ab343" -dependencies = [ - "aho-corasick", - "memchr", - "regex-automata", - "regex-syntax", -] - -[[package]] -name = "regex-automata" -version = "0.4.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5f804c7828047e88b2d32e2d7fe5a105da8ee3264f01902f796c8e067dc2483f" -dependencies = [ - "aho-corasick", - "memchr", - "regex-syntax", -] - -[[package]] -name = "regex-syntax" -version = "0.8.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c08c74e62047bb2de4ff487b251e4a92e24f48745648451635cec7d591162d9f" - -[[package]] -name = "ccc_flutter_bridge" -version = "0.1.0" -dependencies = [ - "flutter_rust_bridge", -] - -[[package]] -name = "rustc-demangle" -version = "0.1.23" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d626bb9dae77e28219937af045c257c28bfd3f69333c512553507f5f9798cb76" - -[[package]] -name = "slab" -version = "0.4.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8f92a496fb766b417c996b9c5e57daf2f7ad3b0bebe1ccfca4856390e3d3bb67" -dependencies = [ - "autocfg", -] - -[[package]] -name = "syn" -version = "2.0.39" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "23e78b90f2fcf45d3e842032ce32e3f2d1545ba6636271dcbf24fa306d87be7a" -dependencies = [ - "proc-macro2", - "quote", - "unicode-ident", -] - -[[package]] -name = "threadpool" -version = "1.8.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d050e60b33d41c19108b32cea32164033a9013fe3b46cbd4457559bfbf77afaa" -dependencies = [ - "num_cpus", -] - -[[package]] -name = "tokio" -version = "1.34.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d0c014766411e834f7af5b8f4cf46257aab4036ca95e9d2c144a10f59ad6f5b9" -dependencies = [ - "backtrace", - "num_cpus", - "pin-project-lite", -] - -[[package]] -name = "typenum" -version = "1.17.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "42ff0bf0c66b8238c6f3b578df37d0b7848e55df8577b3f74f92a69acceeb825" - -[[package]] -name = "unicode-ident" -version = "1.0.12" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3354b9ac3fae1ff6755cb6db53683adb661634f67557942dea4facebec0fee4b" - -[[package]] -name = "version_check" -version = "0.9.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "49874b5167b65d7193b8aba1567f5c7d93d001cafc34600cee003eda787e483f" - -[[package]] -name = "wasm-bindgen" -version = "0.2.92" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4be2531df63900aeb2bca0daaaddec08491ee64ceecbee5076636a3b026795a8" -dependencies = [ - "cfg-if", - "wasm-bindgen-macro", -] - -[[package]] -name = "wasm-bindgen-backend" -version = "0.2.92" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "614d787b966d3989fa7bb98a654e369c762374fd3213d212cfc0251257e747da" -dependencies = [ - "bumpalo", - "log", - "once_cell", - "proc-macro2", - "quote", - "syn", - "wasm-bindgen-shared", -] - -[[package]] -name = "wasm-bindgen-futures" -version = "0.4.42" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "76bc14366121efc8dbb487ab05bcc9d346b3b5ec0eaa76e46594cabbe51762c0" -dependencies = [ - "cfg-if", - "js-sys", - "wasm-bindgen", - "web-sys", -] - -[[package]] -name = "wasm-bindgen-macro" -version = "0.2.92" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a1f8823de937b71b9460c0c34e25f3da88250760bec0ebac694b49997550d726" -dependencies = [ - "quote", - "wasm-bindgen-macro-support", -] - -[[package]] -name = "wasm-bindgen-macro-support" -version = "0.2.92" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e94f17b526d0a461a191c78ea52bbce64071ed5c04c9ffe424dcb38f74171bb7" -dependencies = [ - "proc-macro2", - "quote", - "syn", - "wasm-bindgen-backend", - "wasm-bindgen-shared", -] - -[[package]] -name = "wasm-bindgen-shared" -version = "0.2.92" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "af190c94f2773fdb3729c55b007a722abb5384da03bc0986df4c289bf5567e96" - -[[package]] -name = "web-sys" -version = "0.3.66" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "50c24a44ec86bb68fbecd1b3efed7e85ea5621b39b35ef2766b66cd984f8010f" -dependencies = [ - "js-sys", - "wasm-bindgen", -] diff --git a/crates/ccc-flutter-bridge/Cargo.toml b/crates/ccc-flutter-bridge/Cargo.toml deleted file mode 100644 index 54c7166..0000000 --- a/crates/ccc-flutter-bridge/Cargo.toml +++ /dev/null @@ -1,28 +0,0 @@ -[package] -name = "ccc-flutter-bridge" -version = { workspace = true } -edition = { workspace = true } -authors = { workspace = true } -description = "flutter_rust_bridge v2 entry-point exposing CCC Rust crypto to Dart" - -# Both output kinds are required: -# - staticlib → iOS (linked into XCFramework / Runner) -# - cdylib → macOS / Android (.dylib / .so) -[lib] -crate-type = ["cdylib", "staticlib"] - -[dependencies] -ccc-crypto-core = { path = "../ccc-crypto-core" } -ccc-crypto-wolfssl = { path = "../ccc-crypto-wolfssl" } - -flutter_rust_bridge = { version = "=2.11.1" } -zeroize = { workspace = true } -log = { workspace = true } -anyhow = { workspace = true } -env_logger = { workspace = true } - -# Convenience hex encoding for test / debug bridge calls. -hex = "0.4" - -[dev-dependencies] -# Nothing needed; actual tests live in tests/conformance/. diff --git a/crates/ccc-flutter-bridge/include/ccc_bridge.h b/crates/ccc-flutter-bridge/include/ccc_bridge.h deleted file mode 100644 index ad87ade..0000000 --- a/crates/ccc-flutter-bridge/include/ccc_bridge.h +++ /dev/null @@ -1 +0,0 @@ -// Nothing when using full_dep=false mode \ No newline at end of file diff --git a/crates/ccc-flutter-bridge/src/api/mod.rs b/crates/ccc-flutter-bridge/src/api/mod.rs deleted file mode 100644 index b252f36..0000000 --- a/crates/ccc-flutter-bridge/src/api/mod.rs +++ /dev/null @@ -1 +0,0 @@ -pub mod simple; diff --git a/crates/ccc-flutter-bridge/src/api/simple.rs b/crates/ccc-flutter-bridge/src/api/simple.rs deleted file mode 100644 index 4360c82..0000000 --- a/crates/ccc-flutter-bridge/src/api/simple.rs +++ /dev/null @@ -1,10 +0,0 @@ -#[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(); -} diff --git a/crates/ccc-flutter-bridge/src/bridge.rs b/crates/ccc-flutter-bridge/src/bridge.rs deleted file mode 100644 index fa905da..0000000 --- a/crates/ccc-flutter-bridge/src/bridge.rs +++ /dev/null @@ -1,281 +0,0 @@ -//! Public bridge functions — annotated with `#[frb(sync)]` or `#[frb]` so -//! that `flutter_rust_bridge` code-generation emits matching Dart APIs. -//! -//! All fallible functions return `anyhow::Result` (FRB v2 maps that to a -//! Dart `Future` that throws on error). -//! -//! # Naming convention -//! Functions are named `ccc__` so the generated Dart class -//! is pleasingly namespaced as `CccBridge.xxxYyy(…)`. - -use flutter_rust_bridge::frb; -use zeroize::Zeroizing; - -use ccc_crypto_core::{ - algorithms::{AeadAlgorithm, HashAlgorithm, KdfAlgorithm, KemAlgorithm, MacAlgorithm}, - registry::ProviderRegistry, -}; -// Provider traits are imported for use in future dispatch methods. -#[allow(unused_imports)] -use ccc_crypto_core::provider::{AeadProvider, HashProvider, KdfProvider, KemProvider, MacProvider}; - -use super::dto::{ - AeadEncryptRequest, AeadEncryptResult, AlgorithmCapabilityDto, HashRequest, KdfDeriveRequest, - KemEncapResultDto, KemKeyPairDto, MacComputeRequest, ProviderCapabilitiesDto, - SelfTestReportDto, -}; - -// ────────────────────────────────────────────────────────────────────────────── -// Initialisation -// ────────────────────────────────────────────────────────────────────────────── - -/// Initialise the CCC Rust layer. -/// -/// **Must** be called once before any other bridge function, typically during -/// the app's boot sequence in `main.dart` (or `AppState.init()`). -/// -/// Registers the wolfSSL provider into the global [`ProviderRegistry`]. -/// Subsequent calls are no-ops. -#[frb(sync)] -pub fn ccc_init() { - static ONCE: std::sync::OnceLock<()> = std::sync::OnceLock::new(); - ONCE.get_or_init(|| { - let _ = env_logger::try_init(); // tolerate error when already initialised - ccc_crypto_wolfssl::init(); - log::info!("[ccc-bridge] wolfSSL provider registered"); - }); -} - -// ────────────────────────────────────────────────────────────────────────────── -// Provider registry queries -// ────────────────────────────────────────────────────────────────────────────── - -/// List all registered provider names. -#[frb(sync)] -pub fn ccc_list_providers() -> Vec { - ProviderRegistry::global().list() -} - -/// Retrieve full capabilities for a named provider. -/// -/// Returns `None` if the provider is not registered. -#[frb(sync)] -pub fn ccc_capabilities(provider_name: String) -> Option { - let reg = ProviderRegistry::global(); - let guard = reg.get(&provider_name)?; - Some(guard.capabilities().into()) -} - -/// List all algorithms of a specific family that are **available** in a provider. -/// -/// `family` is one of `"aead"`, `"kdf"`, `"mac"`, `"hash"`, `"kem"`. -#[frb(sync)] -pub fn ccc_available_algorithms( - provider_name: String, - family: String, -) -> Vec { - let reg = ProviderRegistry::global(); - let Some(guard) = reg.get(&provider_name) else { return vec![] }; - - // Convert the full capability map to DTO (which flattens HashMaps → Vecs). - let caps_dto: ProviderCapabilitiesDto = guard.capabilities().into(); - - let mut list = match family.as_str() { - "aead" => caps_dto.aead, - "kdf" => caps_dto.kdf, - "mac" => caps_dto.mac, - "hash" => caps_dto.hash, - "kem" => caps_dto.kem, - _ => vec![], - }; - - list.retain(|c| c.available); - list -} - -// ────────────────────────────────────────────────────────────────────────────── -// AEAD -// ────────────────────────────────────────────────────────────────────────────── - -/// Encrypt with an AEAD cipher. -/// -/// Returns `ciphertext || 16-byte authentication tag` on success. -/// -/// # Errors -/// Propagates [`ccc_crypto_core::error::CryptoError`] as an `anyhow::Result`. -pub fn ccc_aead_encrypt(req: AeadEncryptRequest) -> anyhow::Result { - let algo = AeadAlgorithm::from_u32(req.algo_id) - .ok_or_else(|| anyhow::anyhow!("unknown AEAD algo_id: {}", req.algo_id))?; - - let reg = ProviderRegistry::global(); - let guard = reg - .get("wolfssl") - .ok_or_else(|| anyhow::anyhow!("wolfssl provider not registered"))?; - - let ct_tag = guard.encrypt_aead(algo, &req.key, &req.nonce, &req.plaintext, &req.aad)?; - Ok(AeadEncryptResult { ciphertext_and_tag: ct_tag }) -} - -/// Decrypt with an AEAD cipher. -/// -/// Expects `ciphertext || 16-byte authentication tag` as `ciphertext_and_tag`. -/// Returns plaintext on success; returns an error if authentication fails. -pub fn ccc_aead_decrypt( - algo_id: u32, - key: Vec, - nonce: Vec, - ciphertext_and_tag: Vec, - aad: Vec, -) -> anyhow::Result> { - let algo = AeadAlgorithm::from_u32(algo_id) - .ok_or_else(|| anyhow::anyhow!("unknown AEAD algo_id: {}", algo_id))?; - - let reg = ProviderRegistry::global(); - let guard = reg - .get("wolfssl") - .ok_or_else(|| anyhow::anyhow!("wolfssl provider not registered"))?; - - Ok(guard.decrypt_aead(algo, &key, &nonce, &ciphertext_and_tag, &aad)?) -} - -// ────────────────────────────────────────────────────────────────────────────── -// KDF -// ────────────────────────────────────────────────────────────────────────────── - -/// Derive a key using a KDF. -/// -/// Returns the derived key bytes (length = `req.out_length`). -pub fn ccc_kdf_derive(req: KdfDeriveRequest) -> anyhow::Result> { - let algo = KdfAlgorithm::from_u32(req.algo_id) - .ok_or_else(|| anyhow::anyhow!("unknown KDF algo_id: {}", req.algo_id))?; - - let reg = ProviderRegistry::global(); - let guard = reg - .get("wolfssl") - .ok_or_else(|| anyhow::anyhow!("wolfssl provider not registered"))?; - - let out: Zeroizing> = - guard.derive_key(algo, &req.ikm, &req.salt, &req.info, req.out_length as usize)?; - - // Dart does not share memory with Rust; returning a plain Vec is safe. - Ok(out.to_vec()) -} - -// ────────────────────────────────────────────────────────────────────────────── -// MAC -// ────────────────────────────────────────────────────────────────────────────── - -/// Compute a MAC tag. -pub fn ccc_mac_compute(req: MacComputeRequest) -> anyhow::Result> { - let algo = MacAlgorithm::from_u32(req.algo_id) - .ok_or_else(|| anyhow::anyhow!("unknown MAC algo_id: {}", req.algo_id))?; - - let reg = ProviderRegistry::global(); - let guard = reg - .get("wolfssl") - .ok_or_else(|| anyhow::anyhow!("wolfssl provider not registered"))?; - - Ok(guard.compute_mac(algo, &req.key, &req.data)?) -} - -/// Verify a MAC tag in constant time (returns `true` if authentic). -pub fn ccc_mac_verify( - algo_id: u32, - key: Vec, - data: Vec, - mac_bytes: Vec, -) -> anyhow::Result { - let algo = MacAlgorithm::from_u32(algo_id) - .ok_or_else(|| anyhow::anyhow!("unknown MAC algo_id: {}", algo_id))?; - - let reg = ProviderRegistry::global(); - let guard = reg - .get("wolfssl") - .ok_or_else(|| anyhow::anyhow!("wolfssl provider not registered"))?; - - Ok(guard.verify_mac(algo, &key, &data, &mac_bytes)?) -} - -// ────────────────────────────────────────────────────────────────────────────── -// Hash -// ────────────────────────────────────────────────────────────────────────────── - -/// Compute a cryptographic hash. -pub fn ccc_hash(req: HashRequest) -> anyhow::Result> { - let algo = HashAlgorithm::from_u32(req.algo_id) - .ok_or_else(|| anyhow::anyhow!("unknown Hash algo_id: {}", req.algo_id))?; - - let reg = ProviderRegistry::global(); - let guard = reg - .get("wolfssl") - .ok_or_else(|| anyhow::anyhow!("wolfssl provider not registered"))?; - - Ok(guard.hash(algo, &req.data)?) -} - -// ────────────────────────────────────────────────────────────────────────────── -// KEM -// ────────────────────────────────────────────────────────────────────────────── - -/// Generate a KEM key pair. -pub fn ccc_kem_generate_keypair(algo_id: u32) -> anyhow::Result { - let algo = KemAlgorithm::from_u32(algo_id) - .ok_or_else(|| anyhow::anyhow!("unknown KEM algo_id: {}", algo_id))?; - - let reg = ProviderRegistry::global(); - let guard = reg - .get("wolfssl") - .ok_or_else(|| anyhow::anyhow!("wolfssl provider not registered"))?; - - // WolfSslProvider also implements KemProvider. - // Down-cast via concrete type via the global init path. - use ccc_crypto_wolfssl::provider::WolfSslProvider; - let _ = guard; // release the Arc lock before constructing a temporary - - let temp = WolfSslProvider::new(); - Ok(temp.generate_keypair(algo)?.into()) -} - -/// Encapsulate a shared secret to a public key. -pub fn ccc_kem_encapsulate(algo_id: u32, public_key: Vec) -> anyhow::Result { - let algo = KemAlgorithm::from_u32(algo_id) - .ok_or_else(|| anyhow::anyhow!("unknown KEM algo_id: {}", algo_id))?; - - use ccc_crypto_wolfssl::provider::WolfSslProvider; - let temp = WolfSslProvider::new(); - Ok(temp.encapsulate(algo, &public_key)?.into()) -} - -/// Decapsulate a shared secret using a private key. -/// -/// Returns the shared secret bytes. -pub fn ccc_kem_decapsulate( - algo_id: u32, - private_key: Vec, - ciphertext: Vec, -) -> anyhow::Result> { - let algo = KemAlgorithm::from_u32(algo_id) - .ok_or_else(|| anyhow::anyhow!("unknown KEM algo_id: {}", algo_id))?; - - use ccc_crypto_wolfssl::provider::WolfSslProvider; - let temp = WolfSslProvider::new(); - let secret: Zeroizing> = temp.decapsulate(algo, &private_key, &ciphertext)?; - Ok(secret.to_vec()) -} - -// ────────────────────────────────────────────────────────────────────────────── -// Self-test -// ────────────────────────────────────────────────────────────────────────────── - -/// Run the embedded NIST / RFC test vectors for the wolfSSL provider. -/// -/// Returns a full [`SelfTestReportDto`]; `all_passed == true` means every -/// algorithm passed its vectors. Check individual `results` for details. -pub fn ccc_self_test() -> anyhow::Result { - let reg = ProviderRegistry::global(); - let guard = reg - .get("wolfssl") - .ok_or_else(|| anyhow::anyhow!("wolfssl provider not registered"))?; - - Ok(guard.self_test().into()) -} diff --git a/crates/ccc-flutter-bridge/src/dto.rs b/crates/ccc-flutter-bridge/src/dto.rs deleted file mode 100644 index 21fff22..0000000 --- a/crates/ccc-flutter-bridge/src/dto.rs +++ /dev/null @@ -1,296 +0,0 @@ -//! Data Transfer Objects (DTOs) shared between Rust and the Dart layer. -//! -//! All structs here are annotated with `#[frb(opaque)]` or plain `pub struct` -//! as appropriate so that `flutter_rust_bridge` code-generation emits the -//! correct Dart equivalents. -//! -//! **Wire conventions** -//! - Binary blobs are always `Vec` (Dart: `Uint8List`) -//! - Identifiers that mirror `cipher_constants.dart` integers are `u32` -//! - Strings are `String` / `Option` -//! - Boolean results are `bool` - -use flutter_rust_bridge::frb; - -// ────────────────────────────────────────────────────────────────────────────── -// Capability DTOs -// ────────────────────────────────────────────────────────────────────────────── - -/// Capability entry for a single algorithm exported to Dart. -/// -/// Maps 1-to-1 with [`ccc_crypto_core::capabilities::AlgorithmCapability`]. -#[derive(Debug, Clone)] -#[frb(dart_metadata = ("freezed"))] -pub struct AlgorithmCapabilityDto { - /// Algorithm integer id (mirrors `cipher_constants.dart`). - pub algo_id: u32, - /// Human-readable name (e.g. `"AES-256-GCM"`). - pub algo_name: String, - /// Whether the provider actually supports this algorithm. - pub available: bool, - /// Whether the algorithm is deterministic given the same inputs. - pub deterministic_io: bool, - /// Provider-normalised throughput score 0–100 (0 = unknown). - pub efficiency_score: u8, - /// NIST / standards reliability score 0–100 (100 = NIST-recommended). - pub reliability_score: u8, -} - -/// All capabilities returned by a provider in one call. -#[derive(Debug, Clone)] -#[frb(dart_metadata = ("freezed"))] -pub struct ProviderCapabilitiesDto { - pub provider_name: String, - pub aead: Vec, - pub kdf: Vec, - pub mac: Vec, - pub hash: Vec, - pub kem: Vec, -} - -// ────────────────────────────────────────────────────────────────────────────── -// AEAD -// ────────────────────────────────────────────────────────────────────────────── - -/// Input parameters for AEAD encrypt. -#[derive(Debug)] -#[frb(dart_metadata = ("freezed"))] -pub struct AeadEncryptRequest { - /// Algorithm id (e.g. 12 = AES-256-GCM). - pub algo_id: u32, - pub key: Vec, - pub nonce: Vec, - pub plaintext: Vec, - pub aad: Vec, -} - -/// Result of AEAD encrypt: `ciphertext || 16-byte tag`. -#[derive(Debug)] -#[frb(dart_metadata = ("freezed"))] -pub struct AeadEncryptResult { - /// `ciphertext || authentication_tag` (always 16-byte tag appended). - pub ciphertext_and_tag: Vec, -} - -// ────────────────────────────────────────────────────────────────────────────── -// KDF -// ────────────────────────────────────────────────────────────────────────────── - -/// Input parameters for key derivation. -#[derive(Debug)] -#[frb(dart_metadata = ("freezed"))] -pub struct KdfDeriveRequest { - /// Algorithm id (e.g. 1 = HKDF-SHA-256). - pub algo_id: u32, - pub ikm: Vec, - pub salt: Vec, - pub info: Vec, - /// Requested output length in bytes. - pub out_length: u32, -} - -// ────────────────────────────────────────────────────────────────────────────── -// MAC -// ────────────────────────────────────────────────────────────────────────────── - -/// Input parameters for MAC computation. -#[derive(Debug)] -#[frb(dart_metadata = ("freezed"))] -pub struct MacComputeRequest { - /// Algorithm id (e.g. 30 = HMAC-SHA-256). - pub algo_id: u32, - pub key: Vec, - pub data: Vec, -} - -// ────────────────────────────────────────────────────────────────────────────── -// Hash -// ────────────────────────────────────────────────────────────────────────────── - -/// Input parameters for a hash computation. -#[derive(Debug)] -#[frb(dart_metadata = ("freezed"))] -pub struct HashRequest { - /// Algorithm id (e.g. 40 = SHA-256). - pub algo_id: u32, - pub data: Vec, -} - -// ────────────────────────────────────────────────────────────────────────────── -// KEM -// ────────────────────────────────────────────────────────────────────────────── - -/// A generated KEM key pair returned to Dart. -#[derive(Debug, Clone)] -#[frb(dart_metadata = ("freezed"))] -pub struct KemKeyPairDto { - pub private_key: Vec, - pub public_key: Vec, -} - -/// Result of KEM encapsulation. -#[derive(Debug, Clone)] -#[frb(dart_metadata = ("freezed"))] -pub struct KemEncapResultDto { - /// The ephemeral ciphertext to send to the peer. - pub ciphertext: Vec, - /// The shared secret (zeroized after serialisation — Dart copy is its own). - pub shared_secret: Vec, -} - -// ────────────────────────────────────────────────────────────────────────────── -// Self-test -// ────────────────────────────────────────────────────────────────────────────── - -/// Result of a single algorithm self-test. -#[derive(Debug, Clone)] -#[frb(dart_metadata = ("freezed"))] -pub struct AlgoTestResultDto { - pub algo_id: u32, - pub algo_name: String, - pub passed: bool, - pub error_message: Option, -} - -/// Aggregate self-test report returned to Dart after `ccc_self_test()`. -#[derive(Debug, Clone)] -#[frb(dart_metadata = ("freezed"))] -pub struct SelfTestReportDto { - pub provider_name: String, - pub all_passed: bool, - pub results: Vec, -} - -// ────────────────────────────────────────────────────────────────────────────── -// Conversions from core types → DTOs -// ────────────────────────────────────────────────────────────────────────────── - -use ccc_crypto_core::{ - algorithms::{AeadAlgorithm, HashAlgorithm, KdfAlgorithm, KemAlgorithm, MacAlgorithm}, - capabilities::{AlgorithmCapability, ProviderCapabilities}, - types::{AlgoTestResult, KemEncapResult, KemKeyPair, SelfTestReport}, -}; - -// ────────────────────────────────────────────────────────────────────────────── -// Helper — convert a HashMap to a Vec -// ────────────────────────────────────────────────────────────────────────────── - -fn aead_cap_to_dto(algo: AeadAlgorithm, c: AlgorithmCapability) -> AlgorithmCapabilityDto { - AlgorithmCapabilityDto { - algo_id: algo as u32, - algo_name: algo.name().to_string(), - available: c.available, - deterministic_io: c.deterministic_io, - efficiency_score: c.efficiency_score, - reliability_score: c.reliability_score, - } -} - -fn kdf_cap_to_dto(algo: KdfAlgorithm, c: AlgorithmCapability) -> AlgorithmCapabilityDto { - AlgorithmCapabilityDto { - algo_id: algo as u32, - algo_name: algo.name().to_string(), - available: c.available, - deterministic_io: c.deterministic_io, - efficiency_score: c.efficiency_score, - reliability_score: c.reliability_score, - } -} - -fn mac_cap_to_dto(algo: MacAlgorithm, c: AlgorithmCapability) -> AlgorithmCapabilityDto { - AlgorithmCapabilityDto { - algo_id: algo as u32, - algo_name: algo.name().to_string(), - available: c.available, - deterministic_io: c.deterministic_io, - efficiency_score: c.efficiency_score, - reliability_score: c.reliability_score, - } -} - -fn hash_cap_to_dto(algo: HashAlgorithm, c: AlgorithmCapability) -> AlgorithmCapabilityDto { - AlgorithmCapabilityDto { - algo_id: algo as u32, - algo_name: algo.name().to_string(), - available: c.available, - deterministic_io: c.deterministic_io, - efficiency_score: c.efficiency_score, - reliability_score: c.reliability_score, - } -} - -fn kem_cap_to_dto(algo: KemAlgorithm, c: AlgorithmCapability) -> AlgorithmCapabilityDto { - AlgorithmCapabilityDto { - algo_id: algo as u32, - algo_name: algo.name().to_string(), - available: c.available, - deterministic_io: c.deterministic_io, - efficiency_score: c.efficiency_score, - reliability_score: c.reliability_score, - } -} - -impl From for ProviderCapabilitiesDto { - fn from(p: ProviderCapabilities) -> Self { - let mut aead: Vec = - p.aead.into_iter().map(|(a, c)| aead_cap_to_dto(a, c)).collect(); - let mut kdf: Vec = - p.kdf.into_iter().map(|(a, c)| kdf_cap_to_dto(a, c)).collect(); - let mut mac: Vec = - p.mac.into_iter().map(|(a, c)| mac_cap_to_dto(a, c)).collect(); - let mut hash: Vec = - p.hash.into_iter().map(|(a, c)| hash_cap_to_dto(a, c)).collect(); - let mut kem: Vec = - p.kem.into_iter().map(|(a, c)| kem_cap_to_dto(a, c)).collect(); - - // Sort by algo_id for stable ordering in the Dart layer. - aead.sort_by_key(|c| c.algo_id); - kdf.sort_by_key(|c| c.algo_id); - mac.sort_by_key(|c| c.algo_id); - hash.sort_by_key(|c| c.algo_id); - kem.sort_by_key(|c| c.algo_id); - - Self { provider_name: p.provider_name, aead, kdf, mac, hash, kem } - } -} - -impl From for KemKeyPairDto { - fn from(kp: KemKeyPair) -> Self { - // Use .clone() because KemKeyPair implements ZeroizeOnDrop (adds Drop), - // which prevents partial moves in safe Rust. - Self { - private_key: kp.private_key.clone(), - public_key: kp.public_key.clone(), - } - } -} - -impl From for KemEncapResultDto { - fn from(r: KemEncapResult) -> Self { - Self { - ciphertext: r.ciphertext.clone(), - shared_secret: r.shared_secret.clone(), - } - } -} - -impl From for AlgoTestResultDto { - fn from(r: AlgoTestResult) -> Self { - Self { - algo_id: r.algo_id, - algo_name: r.algo_name, - passed: r.passed, - error_message: r.error_message, - } - } -} - -impl From for SelfTestReportDto { - fn from(r: SelfTestReport) -> Self { - Self { - provider_name: r.provider_name, - all_passed: r.all_passed, - results: r.results.into_iter().map(Into::into).collect(), - } - } -} diff --git a/crates/ccc-flutter-bridge/src/frb_generated.rs b/crates/ccc-flutter-bridge/src/frb_generated.rs deleted file mode 100644 index 9f0ee88..0000000 --- a/crates/ccc-flutter-bridge/src/frb_generated.rs +++ /dev/null @@ -1,1354 +0,0 @@ -// 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 = 1644424377; - -// Section: executor - -flutter_rust_bridge::frb_generated_default_handler!(); - -// Section: wire_funcs - -fn wire__crate__bridge__ccc_aead_decrypt_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::TaskInfo { - debug_name: "ccc_aead_decrypt", - 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); - let api_algo_id = ::sse_decode(&mut deserializer); - let api_key = >::sse_decode(&mut deserializer); - let api_nonce = >::sse_decode(&mut deserializer); - let api_ciphertext_and_tag = >::sse_decode(&mut deserializer); - let api_aad = >::sse_decode(&mut deserializer); - deserializer.end(); - move |context| { - transform_result_sse::<_, flutter_rust_bridge::for_generated::anyhow::Error>( - (move || { - let output_ok = crate::bridge::ccc_aead_decrypt( - api_algo_id, - api_key, - api_nonce, - api_ciphertext_and_tag, - api_aad, - )?; - Ok(output_ok) - })(), - ) - } - }, - ) -} -fn wire__crate__bridge__ccc_aead_encrypt_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::TaskInfo { - debug_name: "ccc_aead_encrypt", - 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); - let api_req = ::sse_decode(&mut deserializer); - deserializer.end(); - move |context| { - transform_result_sse::<_, flutter_rust_bridge::for_generated::anyhow::Error>( - (move || { - let output_ok = crate::bridge::ccc_aead_encrypt(api_req)?; - Ok(output_ok) - })(), - ) - } - }, - ) -} -fn wire__crate__bridge__ccc_available_algorithms_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::TaskInfo { - debug_name: "ccc_available_algorithms", - 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_provider_name = ::sse_decode(&mut deserializer); - let api_family = ::sse_decode(&mut deserializer); - deserializer.end(); - transform_result_sse::<_, ()>((move || { - let output_ok = Result::<_, ()>::Ok(crate::bridge::ccc_available_algorithms( - api_provider_name, - api_family, - ))?; - Ok(output_ok) - })()) - }, - ) -} -fn wire__crate__bridge__ccc_capabilities_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::TaskInfo { - debug_name: "ccc_capabilities", - 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_provider_name = ::sse_decode(&mut deserializer); - deserializer.end(); - transform_result_sse::<_, ()>((move || { - let output_ok = - Result::<_, ()>::Ok(crate::bridge::ccc_capabilities(api_provider_name))?; - Ok(output_ok) - })()) - }, - ) -} -fn wire__crate__bridge__ccc_hash_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::TaskInfo { - debug_name: "ccc_hash", - 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); - let api_req = ::sse_decode(&mut deserializer); - deserializer.end(); - move |context| { - transform_result_sse::<_, flutter_rust_bridge::for_generated::anyhow::Error>( - (move || { - let output_ok = crate::bridge::ccc_hash(api_req)?; - Ok(output_ok) - })(), - ) - } - }, - ) -} -fn wire__crate__bridge__ccc_init_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::TaskInfo { - debug_name: "ccc_init", - 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); - deserializer.end(); - transform_result_sse::<_, ()>((move || { - let output_ok = Result::<_, ()>::Ok({ - crate::bridge::ccc_init(); - })?; - Ok(output_ok) - })()) - }, - ) -} -fn wire__crate__bridge__ccc_kdf_derive_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::TaskInfo { - debug_name: "ccc_kdf_derive", - 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); - let api_req = ::sse_decode(&mut deserializer); - deserializer.end(); - move |context| { - transform_result_sse::<_, flutter_rust_bridge::for_generated::anyhow::Error>( - (move || { - let output_ok = crate::bridge::ccc_kdf_derive(api_req)?; - Ok(output_ok) - })(), - ) - } - }, - ) -} -fn wire__crate__bridge__ccc_kem_decapsulate_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::TaskInfo { - debug_name: "ccc_kem_decapsulate", - 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); - let api_algo_id = ::sse_decode(&mut deserializer); - let api_private_key = >::sse_decode(&mut deserializer); - let api_ciphertext = >::sse_decode(&mut deserializer); - deserializer.end(); - move |context| { - transform_result_sse::<_, flutter_rust_bridge::for_generated::anyhow::Error>( - (move || { - let output_ok = crate::bridge::ccc_kem_decapsulate( - api_algo_id, - api_private_key, - api_ciphertext, - )?; - Ok(output_ok) - })(), - ) - } - }, - ) -} -fn wire__crate__bridge__ccc_kem_encapsulate_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::TaskInfo { - debug_name: "ccc_kem_encapsulate", - 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); - let api_algo_id = ::sse_decode(&mut deserializer); - let api_public_key = >::sse_decode(&mut deserializer); - deserializer.end(); - move |context| { - transform_result_sse::<_, flutter_rust_bridge::for_generated::anyhow::Error>( - (move || { - let output_ok = - crate::bridge::ccc_kem_encapsulate(api_algo_id, api_public_key)?; - Ok(output_ok) - })(), - ) - } - }, - ) -} -fn wire__crate__bridge__ccc_kem_generate_keypair_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::TaskInfo { - debug_name: "ccc_kem_generate_keypair", - 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); - let api_algo_id = ::sse_decode(&mut deserializer); - deserializer.end(); - move |context| { - transform_result_sse::<_, flutter_rust_bridge::for_generated::anyhow::Error>( - (move || { - let output_ok = crate::bridge::ccc_kem_generate_keypair(api_algo_id)?; - Ok(output_ok) - })(), - ) - } - }, - ) -} -fn wire__crate__bridge__ccc_list_providers_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::TaskInfo { - debug_name: "ccc_list_providers", - 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); - deserializer.end(); - transform_result_sse::<_, ()>((move || { - let output_ok = Result::<_, ()>::Ok(crate::bridge::ccc_list_providers())?; - Ok(output_ok) - })()) - }, - ) -} -fn wire__crate__bridge__ccc_mac_compute_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::TaskInfo { - debug_name: "ccc_mac_compute", - 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); - let api_req = ::sse_decode(&mut deserializer); - deserializer.end(); - move |context| { - transform_result_sse::<_, flutter_rust_bridge::for_generated::anyhow::Error>( - (move || { - let output_ok = crate::bridge::ccc_mac_compute(api_req)?; - Ok(output_ok) - })(), - ) - } - }, - ) -} -fn wire__crate__bridge__ccc_mac_verify_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::TaskInfo { - debug_name: "ccc_mac_verify", - 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); - let api_algo_id = ::sse_decode(&mut deserializer); - let api_key = >::sse_decode(&mut deserializer); - let api_data = >::sse_decode(&mut deserializer); - let api_mac_bytes = >::sse_decode(&mut deserializer); - deserializer.end(); - move |context| { - transform_result_sse::<_, flutter_rust_bridge::for_generated::anyhow::Error>( - (move || { - let output_ok = crate::bridge::ccc_mac_verify( - api_algo_id, - api_key, - api_data, - api_mac_bytes, - )?; - Ok(output_ok) - })(), - ) - } - }, - ) -} -fn wire__crate__bridge__ccc_self_test_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::TaskInfo { - debug_name: "ccc_self_test", - 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::<_, flutter_rust_bridge::for_generated::anyhow::Error>( - (move || { - let output_ok = crate::bridge::ccc_self_test()?; - Ok(output_ok) - })(), - ) - } - }, - ) -} - -// Section: dart2rust - -impl SseDecode for flutter_rust_bridge::for_generated::anyhow::Error { - // 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 = ::sse_decode(deserializer); - return flutter_rust_bridge::for_generated::anyhow::anyhow!("{}", inner); - } -} - -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 = >::sse_decode(deserializer); - return String::from_utf8(inner).unwrap(); - } -} - -impl SseDecode for crate::dto::AeadEncryptRequest { - // Codec=Sse (Serialization based), see doc to use other codecs - fn sse_decode(deserializer: &mut flutter_rust_bridge::for_generated::SseDeserializer) -> Self { - let mut var_algoId = ::sse_decode(deserializer); - let mut var_key = >::sse_decode(deserializer); - let mut var_nonce = >::sse_decode(deserializer); - let mut var_plaintext = >::sse_decode(deserializer); - let mut var_aad = >::sse_decode(deserializer); - return crate::dto::AeadEncryptRequest { - algo_id: var_algoId, - key: var_key, - nonce: var_nonce, - plaintext: var_plaintext, - aad: var_aad, - }; - } -} - -impl SseDecode for crate::dto::AeadEncryptResult { - // Codec=Sse (Serialization based), see doc to use other codecs - fn sse_decode(deserializer: &mut flutter_rust_bridge::for_generated::SseDeserializer) -> Self { - let mut var_ciphertextAndTag = >::sse_decode(deserializer); - return crate::dto::AeadEncryptResult { - ciphertext_and_tag: var_ciphertextAndTag, - }; - } -} - -impl SseDecode for crate::dto::AlgoTestResultDto { - // Codec=Sse (Serialization based), see doc to use other codecs - fn sse_decode(deserializer: &mut flutter_rust_bridge::for_generated::SseDeserializer) -> Self { - let mut var_algoId = ::sse_decode(deserializer); - let mut var_algoName = ::sse_decode(deserializer); - let mut var_passed = ::sse_decode(deserializer); - let mut var_errorMessage = >::sse_decode(deserializer); - return crate::dto::AlgoTestResultDto { - algo_id: var_algoId, - algo_name: var_algoName, - passed: var_passed, - error_message: var_errorMessage, - }; - } -} - -impl SseDecode for crate::dto::AlgorithmCapabilityDto { - // Codec=Sse (Serialization based), see doc to use other codecs - fn sse_decode(deserializer: &mut flutter_rust_bridge::for_generated::SseDeserializer) -> Self { - let mut var_algoId = ::sse_decode(deserializer); - let mut var_algoName = ::sse_decode(deserializer); - let mut var_available = ::sse_decode(deserializer); - let mut var_deterministicIo = ::sse_decode(deserializer); - let mut var_efficiencyScore = ::sse_decode(deserializer); - let mut var_reliabilityScore = ::sse_decode(deserializer); - return crate::dto::AlgorithmCapabilityDto { - algo_id: var_algoId, - algo_name: var_algoName, - available: var_available, - deterministic_io: var_deterministicIo, - efficiency_score: var_efficiencyScore, - reliability_score: var_reliabilityScore, - }; - } -} - -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 - } -} - -impl SseDecode for crate::dto::HashRequest { - // Codec=Sse (Serialization based), see doc to use other codecs - fn sse_decode(deserializer: &mut flutter_rust_bridge::for_generated::SseDeserializer) -> Self { - let mut var_algoId = ::sse_decode(deserializer); - let mut var_data = >::sse_decode(deserializer); - return crate::dto::HashRequest { - algo_id: var_algoId, - data: var_data, - }; - } -} - -impl SseDecode for crate::dto::KdfDeriveRequest { - // Codec=Sse (Serialization based), see doc to use other codecs - fn sse_decode(deserializer: &mut flutter_rust_bridge::for_generated::SseDeserializer) -> Self { - let mut var_algoId = ::sse_decode(deserializer); - let mut var_ikm = >::sse_decode(deserializer); - let mut var_salt = >::sse_decode(deserializer); - let mut var_info = >::sse_decode(deserializer); - let mut var_outLength = ::sse_decode(deserializer); - return crate::dto::KdfDeriveRequest { - algo_id: var_algoId, - ikm: var_ikm, - salt: var_salt, - info: var_info, - out_length: var_outLength, - }; - } -} - -impl SseDecode for crate::dto::KemEncapResultDto { - // Codec=Sse (Serialization based), see doc to use other codecs - fn sse_decode(deserializer: &mut flutter_rust_bridge::for_generated::SseDeserializer) -> Self { - let mut var_ciphertext = >::sse_decode(deserializer); - let mut var_sharedSecret = >::sse_decode(deserializer); - return crate::dto::KemEncapResultDto { - ciphertext: var_ciphertext, - shared_secret: var_sharedSecret, - }; - } -} - -impl SseDecode for crate::dto::KemKeyPairDto { - // Codec=Sse (Serialization based), see doc to use other codecs - fn sse_decode(deserializer: &mut flutter_rust_bridge::for_generated::SseDeserializer) -> Self { - let mut var_privateKey = >::sse_decode(deserializer); - let mut var_publicKey = >::sse_decode(deserializer); - return crate::dto::KemKeyPairDto { - private_key: var_privateKey, - public_key: var_publicKey, - }; - } -} - -impl SseDecode for Vec { - // 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_ = ::sse_decode(deserializer); - let mut ans_ = vec![]; - for idx_ in 0..len_ { - ans_.push(::sse_decode(deserializer)); - } - return ans_; - } -} - -impl SseDecode for Vec { - // 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_ = ::sse_decode(deserializer); - let mut ans_ = vec![]; - for idx_ in 0..len_ { - ans_.push(::sse_decode(deserializer)); - } - return ans_; - } -} - -impl SseDecode for Vec { - // 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_ = ::sse_decode(deserializer); - let mut ans_ = vec![]; - for idx_ in 0..len_ { - ans_.push(::sse_decode( - deserializer, - )); - } - return ans_; - } -} - -impl SseDecode for Vec { - // 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_ = ::sse_decode(deserializer); - let mut ans_ = vec![]; - for idx_ in 0..len_ { - ans_.push(::sse_decode(deserializer)); - } - return ans_; - } -} - -impl SseDecode for crate::dto::MacComputeRequest { - // Codec=Sse (Serialization based), see doc to use other codecs - fn sse_decode(deserializer: &mut flutter_rust_bridge::for_generated::SseDeserializer) -> Self { - let mut var_algoId = ::sse_decode(deserializer); - let mut var_key = >::sse_decode(deserializer); - let mut var_data = >::sse_decode(deserializer); - return crate::dto::MacComputeRequest { - algo_id: var_algoId, - key: var_key, - data: var_data, - }; - } -} - -impl SseDecode for Option { - // Codec=Sse (Serialization based), see doc to use other codecs - fn sse_decode(deserializer: &mut flutter_rust_bridge::for_generated::SseDeserializer) -> Self { - if (::sse_decode(deserializer)) { - return Some(::sse_decode(deserializer)); - } else { - return None; - } - } -} - -impl SseDecode for Option { - // Codec=Sse (Serialization based), see doc to use other codecs - fn sse_decode(deserializer: &mut flutter_rust_bridge::for_generated::SseDeserializer) -> Self { - if (::sse_decode(deserializer)) { - return Some(::sse_decode( - deserializer, - )); - } else { - return None; - } - } -} - -impl SseDecode for crate::dto::ProviderCapabilitiesDto { - // Codec=Sse (Serialization based), see doc to use other codecs - fn sse_decode(deserializer: &mut flutter_rust_bridge::for_generated::SseDeserializer) -> Self { - let mut var_providerName = ::sse_decode(deserializer); - let mut var_aead = >::sse_decode(deserializer); - let mut var_kdf = >::sse_decode(deserializer); - let mut var_mac = >::sse_decode(deserializer); - let mut var_hash = >::sse_decode(deserializer); - let mut var_kem = >::sse_decode(deserializer); - return crate::dto::ProviderCapabilitiesDto { - provider_name: var_providerName, - aead: var_aead, - kdf: var_kdf, - mac: var_mac, - hash: var_hash, - kem: var_kem, - }; - } -} - -impl SseDecode for crate::dto::SelfTestReportDto { - // Codec=Sse (Serialization based), see doc to use other codecs - fn sse_decode(deserializer: &mut flutter_rust_bridge::for_generated::SseDeserializer) -> Self { - let mut var_providerName = ::sse_decode(deserializer); - let mut var_allPassed = ::sse_decode(deserializer); - let mut var_results = >::sse_decode(deserializer); - return crate::dto::SelfTestReportDto { - provider_name: var_providerName, - all_passed: var_allPassed, - results: var_results, - }; - } -} - -impl SseDecode for u32 { - // 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_u32::().unwrap() - } -} - -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::().unwrap() - } -} - -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 { - 1 => wire__crate__bridge__ccc_aead_decrypt_impl(port, ptr, rust_vec_len, data_len), - 2 => wire__crate__bridge__ccc_aead_encrypt_impl(port, ptr, rust_vec_len, data_len), - 5 => wire__crate__bridge__ccc_hash_impl(port, ptr, rust_vec_len, data_len), - 7 => wire__crate__bridge__ccc_kdf_derive_impl(port, ptr, rust_vec_len, data_len), - 8 => wire__crate__bridge__ccc_kem_decapsulate_impl(port, ptr, rust_vec_len, data_len), - 9 => wire__crate__bridge__ccc_kem_encapsulate_impl(port, ptr, rust_vec_len, data_len), - 10 => wire__crate__bridge__ccc_kem_generate_keypair_impl(port, ptr, rust_vec_len, data_len), - 12 => wire__crate__bridge__ccc_mac_compute_impl(port, ptr, rust_vec_len, data_len), - 13 => wire__crate__bridge__ccc_mac_verify_impl(port, ptr, rust_vec_len, data_len), - 14 => wire__crate__bridge__ccc_self_test_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 { - 3 => wire__crate__bridge__ccc_available_algorithms_impl(ptr, rust_vec_len, data_len), - 4 => wire__crate__bridge__ccc_capabilities_impl(ptr, rust_vec_len, data_len), - 6 => wire__crate__bridge__ccc_init_impl(ptr, rust_vec_len, data_len), - 11 => wire__crate__bridge__ccc_list_providers_impl(ptr, rust_vec_len, data_len), - _ => unreachable!(), - } -} - -// Section: rust2dart - -// Codec=Dco (DartCObject based), see doc to use other codecs -impl flutter_rust_bridge::IntoDart for crate::dto::AeadEncryptRequest { - fn into_dart(self) -> flutter_rust_bridge::for_generated::DartAbi { - [ - self.algo_id.into_into_dart().into_dart(), - self.key.into_into_dart().into_dart(), - self.nonce.into_into_dart().into_dart(), - self.plaintext.into_into_dart().into_dart(), - self.aad.into_into_dart().into_dart(), - ] - .into_dart() - } -} -impl flutter_rust_bridge::for_generated::IntoDartExceptPrimitive - for crate::dto::AeadEncryptRequest -{ -} -impl flutter_rust_bridge::IntoIntoDart - for crate::dto::AeadEncryptRequest -{ - fn into_into_dart(self) -> crate::dto::AeadEncryptRequest { - self - } -} -// Codec=Dco (DartCObject based), see doc to use other codecs -impl flutter_rust_bridge::IntoDart for crate::dto::AeadEncryptResult { - fn into_dart(self) -> flutter_rust_bridge::for_generated::DartAbi { - [self.ciphertext_and_tag.into_into_dart().into_dart()].into_dart() - } -} -impl flutter_rust_bridge::for_generated::IntoDartExceptPrimitive for crate::dto::AeadEncryptResult {} -impl flutter_rust_bridge::IntoIntoDart - for crate::dto::AeadEncryptResult -{ - fn into_into_dart(self) -> crate::dto::AeadEncryptResult { - self - } -} -// Codec=Dco (DartCObject based), see doc to use other codecs -impl flutter_rust_bridge::IntoDart for crate::dto::AlgoTestResultDto { - fn into_dart(self) -> flutter_rust_bridge::for_generated::DartAbi { - [ - self.algo_id.into_into_dart().into_dart(), - self.algo_name.into_into_dart().into_dart(), - self.passed.into_into_dart().into_dart(), - self.error_message.into_into_dart().into_dart(), - ] - .into_dart() - } -} -impl flutter_rust_bridge::for_generated::IntoDartExceptPrimitive for crate::dto::AlgoTestResultDto {} -impl flutter_rust_bridge::IntoIntoDart - for crate::dto::AlgoTestResultDto -{ - fn into_into_dart(self) -> crate::dto::AlgoTestResultDto { - self - } -} -// Codec=Dco (DartCObject based), see doc to use other codecs -impl flutter_rust_bridge::IntoDart for crate::dto::AlgorithmCapabilityDto { - fn into_dart(self) -> flutter_rust_bridge::for_generated::DartAbi { - [ - self.algo_id.into_into_dart().into_dart(), - self.algo_name.into_into_dart().into_dart(), - self.available.into_into_dart().into_dart(), - self.deterministic_io.into_into_dart().into_dart(), - self.efficiency_score.into_into_dart().into_dart(), - self.reliability_score.into_into_dart().into_dart(), - ] - .into_dart() - } -} -impl flutter_rust_bridge::for_generated::IntoDartExceptPrimitive - for crate::dto::AlgorithmCapabilityDto -{ -} -impl flutter_rust_bridge::IntoIntoDart - for crate::dto::AlgorithmCapabilityDto -{ - fn into_into_dart(self) -> crate::dto::AlgorithmCapabilityDto { - self - } -} -// Codec=Dco (DartCObject based), see doc to use other codecs -impl flutter_rust_bridge::IntoDart for crate::dto::HashRequest { - fn into_dart(self) -> flutter_rust_bridge::for_generated::DartAbi { - [ - self.algo_id.into_into_dart().into_dart(), - self.data.into_into_dart().into_dart(), - ] - .into_dart() - } -} -impl flutter_rust_bridge::for_generated::IntoDartExceptPrimitive for crate::dto::HashRequest {} -impl flutter_rust_bridge::IntoIntoDart for crate::dto::HashRequest { - fn into_into_dart(self) -> crate::dto::HashRequest { - self - } -} -// Codec=Dco (DartCObject based), see doc to use other codecs -impl flutter_rust_bridge::IntoDart for crate::dto::KdfDeriveRequest { - fn into_dart(self) -> flutter_rust_bridge::for_generated::DartAbi { - [ - self.algo_id.into_into_dart().into_dart(), - self.ikm.into_into_dart().into_dart(), - self.salt.into_into_dart().into_dart(), - self.info.into_into_dart().into_dart(), - self.out_length.into_into_dart().into_dart(), - ] - .into_dart() - } -} -impl flutter_rust_bridge::for_generated::IntoDartExceptPrimitive for crate::dto::KdfDeriveRequest {} -impl flutter_rust_bridge::IntoIntoDart - for crate::dto::KdfDeriveRequest -{ - fn into_into_dart(self) -> crate::dto::KdfDeriveRequest { - self - } -} -// Codec=Dco (DartCObject based), see doc to use other codecs -impl flutter_rust_bridge::IntoDart for crate::dto::KemEncapResultDto { - fn into_dart(self) -> flutter_rust_bridge::for_generated::DartAbi { - [ - self.ciphertext.into_into_dart().into_dart(), - self.shared_secret.into_into_dart().into_dart(), - ] - .into_dart() - } -} -impl flutter_rust_bridge::for_generated::IntoDartExceptPrimitive for crate::dto::KemEncapResultDto {} -impl flutter_rust_bridge::IntoIntoDart - for crate::dto::KemEncapResultDto -{ - fn into_into_dart(self) -> crate::dto::KemEncapResultDto { - self - } -} -// Codec=Dco (DartCObject based), see doc to use other codecs -impl flutter_rust_bridge::IntoDart for crate::dto::KemKeyPairDto { - fn into_dart(self) -> flutter_rust_bridge::for_generated::DartAbi { - [ - self.private_key.into_into_dart().into_dart(), - self.public_key.into_into_dart().into_dart(), - ] - .into_dart() - } -} -impl flutter_rust_bridge::for_generated::IntoDartExceptPrimitive for crate::dto::KemKeyPairDto {} -impl flutter_rust_bridge::IntoIntoDart for crate::dto::KemKeyPairDto { - fn into_into_dart(self) -> crate::dto::KemKeyPairDto { - self - } -} -// Codec=Dco (DartCObject based), see doc to use other codecs -impl flutter_rust_bridge::IntoDart for crate::dto::MacComputeRequest { - fn into_dart(self) -> flutter_rust_bridge::for_generated::DartAbi { - [ - self.algo_id.into_into_dart().into_dart(), - self.key.into_into_dart().into_dart(), - self.data.into_into_dart().into_dart(), - ] - .into_dart() - } -} -impl flutter_rust_bridge::for_generated::IntoDartExceptPrimitive for crate::dto::MacComputeRequest {} -impl flutter_rust_bridge::IntoIntoDart - for crate::dto::MacComputeRequest -{ - fn into_into_dart(self) -> crate::dto::MacComputeRequest { - self - } -} -// Codec=Dco (DartCObject based), see doc to use other codecs -impl flutter_rust_bridge::IntoDart for crate::dto::ProviderCapabilitiesDto { - fn into_dart(self) -> flutter_rust_bridge::for_generated::DartAbi { - [ - self.provider_name.into_into_dart().into_dart(), - self.aead.into_into_dart().into_dart(), - self.kdf.into_into_dart().into_dart(), - self.mac.into_into_dart().into_dart(), - self.hash.into_into_dart().into_dart(), - self.kem.into_into_dart().into_dart(), - ] - .into_dart() - } -} -impl flutter_rust_bridge::for_generated::IntoDartExceptPrimitive - for crate::dto::ProviderCapabilitiesDto -{ -} -impl flutter_rust_bridge::IntoIntoDart - for crate::dto::ProviderCapabilitiesDto -{ - fn into_into_dart(self) -> crate::dto::ProviderCapabilitiesDto { - self - } -} -// Codec=Dco (DartCObject based), see doc to use other codecs -impl flutter_rust_bridge::IntoDart for crate::dto::SelfTestReportDto { - fn into_dart(self) -> flutter_rust_bridge::for_generated::DartAbi { - [ - self.provider_name.into_into_dart().into_dart(), - self.all_passed.into_into_dart().into_dart(), - self.results.into_into_dart().into_dart(), - ] - .into_dart() - } -} -impl flutter_rust_bridge::for_generated::IntoDartExceptPrimitive for crate::dto::SelfTestReportDto {} -impl flutter_rust_bridge::IntoIntoDart - for crate::dto::SelfTestReportDto -{ - fn into_into_dart(self) -> crate::dto::SelfTestReportDto { - self - } -} - -impl SseEncode for flutter_rust_bridge::for_generated::anyhow::Error { - // Codec=Sse (Serialization based), see doc to use other codecs - fn sse_encode(self, serializer: &mut flutter_rust_bridge::for_generated::SseSerializer) { - ::sse_encode(format!("{:?}", self), serializer); - } -} - -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) { - >::sse_encode(self.into_bytes(), serializer); - } -} - -impl SseEncode for crate::dto::AeadEncryptRequest { - // Codec=Sse (Serialization based), see doc to use other codecs - fn sse_encode(self, serializer: &mut flutter_rust_bridge::for_generated::SseSerializer) { - ::sse_encode(self.algo_id, serializer); - >::sse_encode(self.key, serializer); - >::sse_encode(self.nonce, serializer); - >::sse_encode(self.plaintext, serializer); - >::sse_encode(self.aad, serializer); - } -} - -impl SseEncode for crate::dto::AeadEncryptResult { - // Codec=Sse (Serialization based), see doc to use other codecs - fn sse_encode(self, serializer: &mut flutter_rust_bridge::for_generated::SseSerializer) { - >::sse_encode(self.ciphertext_and_tag, serializer); - } -} - -impl SseEncode for crate::dto::AlgoTestResultDto { - // Codec=Sse (Serialization based), see doc to use other codecs - fn sse_encode(self, serializer: &mut flutter_rust_bridge::for_generated::SseSerializer) { - ::sse_encode(self.algo_id, serializer); - ::sse_encode(self.algo_name, serializer); - ::sse_encode(self.passed, serializer); - >::sse_encode(self.error_message, serializer); - } -} - -impl SseEncode for crate::dto::AlgorithmCapabilityDto { - // Codec=Sse (Serialization based), see doc to use other codecs - fn sse_encode(self, serializer: &mut flutter_rust_bridge::for_generated::SseSerializer) { - ::sse_encode(self.algo_id, serializer); - ::sse_encode(self.algo_name, serializer); - ::sse_encode(self.available, serializer); - ::sse_encode(self.deterministic_io, serializer); - ::sse_encode(self.efficiency_score, serializer); - ::sse_encode(self.reliability_score, serializer); - } -} - -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(); - } -} - -impl SseEncode for crate::dto::HashRequest { - // Codec=Sse (Serialization based), see doc to use other codecs - fn sse_encode(self, serializer: &mut flutter_rust_bridge::for_generated::SseSerializer) { - ::sse_encode(self.algo_id, serializer); - >::sse_encode(self.data, serializer); - } -} - -impl SseEncode for crate::dto::KdfDeriveRequest { - // Codec=Sse (Serialization based), see doc to use other codecs - fn sse_encode(self, serializer: &mut flutter_rust_bridge::for_generated::SseSerializer) { - ::sse_encode(self.algo_id, serializer); - >::sse_encode(self.ikm, serializer); - >::sse_encode(self.salt, serializer); - >::sse_encode(self.info, serializer); - ::sse_encode(self.out_length, serializer); - } -} - -impl SseEncode for crate::dto::KemEncapResultDto { - // Codec=Sse (Serialization based), see doc to use other codecs - fn sse_encode(self, serializer: &mut flutter_rust_bridge::for_generated::SseSerializer) { - >::sse_encode(self.ciphertext, serializer); - >::sse_encode(self.shared_secret, serializer); - } -} - -impl SseEncode for crate::dto::KemKeyPairDto { - // Codec=Sse (Serialization based), see doc to use other codecs - fn sse_encode(self, serializer: &mut flutter_rust_bridge::for_generated::SseSerializer) { - >::sse_encode(self.private_key, serializer); - >::sse_encode(self.public_key, serializer); - } -} - -impl SseEncode for Vec { - // Codec=Sse (Serialization based), see doc to use other codecs - fn sse_encode(self, serializer: &mut flutter_rust_bridge::for_generated::SseSerializer) { - ::sse_encode(self.len() as _, serializer); - for item in self { - ::sse_encode(item, serializer); - } - } -} - -impl SseEncode for Vec { - // Codec=Sse (Serialization based), see doc to use other codecs - fn sse_encode(self, serializer: &mut flutter_rust_bridge::for_generated::SseSerializer) { - ::sse_encode(self.len() as _, serializer); - for item in self { - ::sse_encode(item, serializer); - } - } -} - -impl SseEncode for Vec { - // Codec=Sse (Serialization based), see doc to use other codecs - fn sse_encode(self, serializer: &mut flutter_rust_bridge::for_generated::SseSerializer) { - ::sse_encode(self.len() as _, serializer); - for item in self { - ::sse_encode(item, serializer); - } - } -} - -impl SseEncode for Vec { - // Codec=Sse (Serialization based), see doc to use other codecs - fn sse_encode(self, serializer: &mut flutter_rust_bridge::for_generated::SseSerializer) { - ::sse_encode(self.len() as _, serializer); - for item in self { - ::sse_encode(item, serializer); - } - } -} - -impl SseEncode for crate::dto::MacComputeRequest { - // Codec=Sse (Serialization based), see doc to use other codecs - fn sse_encode(self, serializer: &mut flutter_rust_bridge::for_generated::SseSerializer) { - ::sse_encode(self.algo_id, serializer); - >::sse_encode(self.key, serializer); - >::sse_encode(self.data, serializer); - } -} - -impl SseEncode for Option { - // Codec=Sse (Serialization based), see doc to use other codecs - fn sse_encode(self, serializer: &mut flutter_rust_bridge::for_generated::SseSerializer) { - ::sse_encode(self.is_some(), serializer); - if let Some(value) = self { - ::sse_encode(value, serializer); - } - } -} - -impl SseEncode for Option { - // Codec=Sse (Serialization based), see doc to use other codecs - fn sse_encode(self, serializer: &mut flutter_rust_bridge::for_generated::SseSerializer) { - ::sse_encode(self.is_some(), serializer); - if let Some(value) = self { - ::sse_encode(value, serializer); - } - } -} - -impl SseEncode for crate::dto::ProviderCapabilitiesDto { - // Codec=Sse (Serialization based), see doc to use other codecs - fn sse_encode(self, serializer: &mut flutter_rust_bridge::for_generated::SseSerializer) { - ::sse_encode(self.provider_name, serializer); - >::sse_encode(self.aead, serializer); - >::sse_encode(self.kdf, serializer); - >::sse_encode(self.mac, serializer); - >::sse_encode(self.hash, serializer); - >::sse_encode(self.kem, serializer); - } -} - -impl SseEncode for crate::dto::SelfTestReportDto { - // Codec=Sse (Serialization based), see doc to use other codecs - fn sse_encode(self, serializer: &mut flutter_rust_bridge::for_generated::SseSerializer) { - ::sse_encode(self.provider_name, serializer); - ::sse_encode(self.all_passed, serializer); - >::sse_encode(self.results, serializer); - } -} - -impl SseEncode for u32 { - // 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_u32::(self).unwrap(); - } -} - -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::(self).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::*; diff --git a/crates/ccc-flutter-bridge/src/lib.rs b/crates/ccc-flutter-bridge/src/lib.rs deleted file mode 100644 index d0e962d..0000000 --- a/crates/ccc-flutter-bridge/src/lib.rs +++ /dev/null @@ -1,22 +0,0 @@ -//! `ccc-flutter-bridge` — flutter_rust_bridge v2 entry-point. -//! -//! This crate is compiled to both a `cdylib` (for macOS / Android) and a -//! `staticlib` (for iOS). Do not add platform logic here — keep it in the -//! provider crates. -//! -//! ## Generated Dart bindings -//! -//! Run the code-generator from the flutter project root: -//! -//! ```sh -//! flutter_rust_bridge_codegen generate -//! ``` -//! -//! The generator reads this crate's source and emits Dart classes under -//! `flutter_src/lib/gen/rust/`. - -// AUTO INJECTED BY flutter_rust_bridge. -mod frb_generated; - -pub mod bridge; -pub mod dto; diff --git a/docs/ccc_rust_plan.rst b/docs/ccc_rust_plan.rst index 02a0144..fd0a3b5 100644 --- a/docs/ccc_rust_plan.rst +++ b/docs/ccc_rust_plan.rst @@ -3,59 +3,74 @@ CCC Rust Crypto Provider — Architecture Plan =============================================== :Status: Approved -:Phase: 4 -:Date: 2026-02-23 +:Phase: 4 — Milestone 1 of 3 +:Date: 2026-02-24 :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. +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 already in - ``cipher_constants.dart`` — zero Dart routing changes needed. +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 / self-test suite validates cross-provider byte-identity +4. A conformance test suite validates NIST/RFC vectors for every algorithm 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. +5. The library has no runtime dependency on Flutter; it is consumable by any + FFI host (Flutter plugin, Python tests, CLI tools). -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) ---------------------------------- +Repository Layout (Milestone 1 — this repo) +-------------------------------------------- :: ccc_rust/ - ├── Cargo.toml ← workspace manifest (3 members) + ├── Cargo.toml ← workspace manifest (3 members, no bridge) ├── rust-toolchain.toml ← pinned stable toolchain ├── .cargo/ │ └── config.toml ← cross-compile target aliases @@ -73,40 +88,26 @@ Repository Layout (target state) │ │ ├── provider.rs ← CryptoProvider umbrella trait │ │ ├── registry.rs ← ProviderRegistry (OnceLock>) │ │ └── 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 + │ └── ccc-crypto-wolfssl/ ← wolfSSL provider implementation │ ├── 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/ + │ ├── 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 ---------------------------------- -Files -~~~~~ - ``Cargo.toml``:: [workspace] @@ -114,21 +115,21 @@ Files members = [ "crates/ccc-crypto-core", "crates/ccc-crypto-wolfssl", - "crates/ccc-flutter-bridge", + "tests/conformance", ] ``rust-toolchain.toml``:: [toolchain] - channel = "1.77" + channel = "stable" ``.cargo/config.toml``:: [alias] - build-ios = "build --target aarch64-apple-ios" + 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" + build-macos = "build --target aarch64-apple-darwin" Step 2 — ``ccc-crypto-core`` Trait Crate ----------------------------------------- @@ -256,16 +257,9 @@ Provider Traits 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 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 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ @@ -273,152 +267,127 @@ 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 +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 (if PQ build) X25519, X448, ML-KEM-768, ML-KEM-1024 +KEM X25519, X448 +KEM (Phase 5) ML-KEM-768, ML-KEM-1024, Classic McEliece =================== =========================================== 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``. +``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 0–100 -``efficiency_score``. Run once at ``ccc_init()`` and cached. +``efficiency_score``. Run once at library 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 - ccc_provider_capabilities(provider) → CapabilitiesDto - ccc_aead_encrypt(provider, algo: u32, key, nonce, plaintext, aad) - → Result> - ccc_aead_decrypt(provider, algo: u32, key, nonce, ciphertext, aad) - → Result> - ccc_derive_key(provider, algo: u32, ikm, salt, info, length: u32) - → Result> - ccc_compute_mac(provider, algo: u32, key, data) - → Result> - ccc_verify_mac(provider, algo: u32, key, data, mac) - → Result - ccc_hash(provider, algo: u32, data) → Result> - ccc_kem_generate_keypair(provider, algo: u32) - → Result - ccc_kem_encapsulate(provider, algo: u32, public_key) - → Result - ccc_kem_decapsulate(provider, algo: u32, private_key, ciphertext) - → Result> - 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, private_key: Vec }`` - -``KemEncapDto { ciphertext: Vec, shared_secret: Vec }`` - -``SelfTestDto { provider: String, results: Vec }`` - -``AlgoTestResult { algo_id: u32, algo_name: String, passed: bool, -error_message: Option }`` - -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> encrypt(Map 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 +Step 4 — Conformance Test Suite --------------------------------- -Location: ``tests/conformance/`` +Location: ``tests/conformance/src/main.rs`` -* ``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``) +Run with ``cargo run -p ccc-conformance-tests`` and ``cargo test --workspace``. -Step 8 — Architecture Documentation +========================= ================================ +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/phase4_rust_architecture.rst`` covers: * Crate dependency graph (ASCII) -* "How to add a new provider" — the 7-step trait checklist +* "How to add a new provider" — 7-step trait checklist * ``algo: u32`` → cipher constant mapping table -* Stretch-goal Phase 8 "Omni-Crypto" provider list +* Milestone 2 hand-off contract (API surface Milestone 2 must implement against) -Phase 8 — Stretch Goal Provider List --------------------------------------- +---- -*(Fully out of scope for Phase 4. Documented here for future planning.)* +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 @@ -435,14 +404,3 @@ 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) diff --git a/docs/ccc_rust_plan_phases.rst b/docs/ccc_rust_plan_phases.rst index 770d8a5..b1ae177 100644 --- a/docs/ccc_rust_plan_phases.rst +++ b/docs/ccc_rust_plan_phases.rst @@ -2,7 +2,7 @@ CCC Rust Implementation — Phase Tracking ============================================== -:Last Updated: 2026-06-20 +:Last Updated: 2026-02-24 Legend ------ @@ -14,10 +14,30 @@ Legend ---- +Three-Milestone Overview +------------------------ + +============= =================================== ============================ +Milestone Repository Status +============= =================================== ============================ +**1 (this)** ``ccc_rust`` In progress +**2** ``ccc_cryptography`` Not started +**3** ``letusmsg`` (existing app) Not started +============= =================================== ============================ + +Milestone 2 does not start until the Milestone 1 Verification Gate passes. +Milestone 3 does not start until the Milestone 2 gate passes. + +---- + +============================================================ +Milestone 1 — ``ccc_rust`` Pure Rust Crypto Library +============================================================ + Step 1 — Cargo Workspace Scaffold ---------------------------------- -* ``[x]`` Create ``Cargo.toml`` (workspace manifest, 4 members) +* ``[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`` @@ -99,280 +119,131 @@ Step 3 — wolfSSL Submodule + ``ccc-crypto-wolfssl`` ---- -Step 4 — ``ccc-flutter-bridge`` Entry-Point Crate ---------------------------------------------------- - -* ``[x]`` Create ``crates/ccc-flutter-bridge/Cargo.toml`` -* ``[x]`` Set ``crate-type = ["cdylib", "staticlib"]`` -* ``[x]`` Add ``flutter_rust_bridge = "=2.9.0"`` dependency -* ``[x]`` ``dto.rs`` — CapabilitiesDto, KemKeyPairDto, KemEncapDto, - SelfTestDto, AlgoTestResultDto; From impls -* ``[x]`` ``bridge.rs`` — ccc_init() -* ``[x]`` ``bridge.rs`` — ccc_list_providers() -* ``[x]`` ``bridge.rs`` — ccc_capabilities() / ccc_available_algorithms() -* ``[x]`` ``bridge.rs`` — ccc_aead_encrypt() / ccc_aead_decrypt() -* ``[x]`` ``bridge.rs`` — ccc_kdf_derive() -* ``[x]`` ``bridge.rs`` — ccc_mac_compute() / ccc_mac_verify() -* ``[x]`` ``bridge.rs`` — ccc_hash() -* ``[x]`` ``bridge.rs`` — ccc_kem_generate_keypair() -* ``[x]`` ``bridge.rs`` — ccc_kem_encapsulate() / ccc_kem_decapsulate() -* ``[x]`` ``bridge.rs`` — ccc_self_test() -* ``[x]`` ``lib.rs`` — module declarations -* ``[x]`` ``flutter_rust_bridge.yaml`` — codegen config - ----- - -Step 5 — Flutter Build Integration ------------------------------------- - -* ``[x]`` Add ``flutter_rust_bridge: ^2`` to ``pubspec.yaml`` -* ``[x]`` Run ``flutter_rust_bridge_codegen generate`` -* ``[x]`` Verify generated ``flutter_src/lib/gen/rust/`` bindings (bridge.dart, dto.dart, dto.freezed.dart, frb_generated.dart) -* ``[ ]`` iOS plugin scaffold (``ios/`` dir, cargokit integration) -* ``[ ]`` Android plugin scaffold (``android/`` dir, CMakeLists.txt) -* ``[ ]`` macOS plugin scaffold (``macos/`` dir) -* ``[ ]`` Confirm ``flutter build ios`` succeeds (static lib linked) -* ``[ ]`` Confirm ``flutter build apk`` succeeds (cdylib linked) - ----- - -Step 6 — Dart Layer Wiring ---------------------------- - -* ``[ ]`` Wire ``crypto_wolfssl.dart`` ``encrypt()`` → ``ccc_aead_encrypt()`` -* ``[ ]`` Wire ``crypto_wolfssl.dart`` ``decrypt()`` → ``ccc_aead_decrypt()`` -* ``[ ]`` Convert ``CccProviderCatalog.capabilities`` to runtime-populated map -* ``[ ]`` Call ``ccc_init()`` at app startup -* ``[ ]`` Populate ``CccProviderCatalog`` from ``ccc_capabilities()`` -* ``[ ]`` Create ``CccSelfTest`` Dart class (wraps ``ccc_self_test()``) -* ``[ ]`` Expose self-test pass/fail diagnostics in app debug screen - ----- - -Step 7 — Conformance Test Suite +Step 4 — Conformance Test Suite --------------------------------- -* ``[x]`` ``tests/conformance/src/main.rs`` — NIST AES-256-GCM (2 vectors) -* ``[x]`` ``tests/conformance/src/main.rs`` — RFC 8439 ChaCha20-Poly1305 -* ``[x]`` ``tests/conformance/src/main.rs`` — RFC 5869 HKDF-SHA256 (2 vectors) -* ``[x]`` ``tests/conformance/src/main.rs`` — RFC 4231 HMAC-SHA256 (2 vectors) -* ``[x]`` ``tests/conformance/src/main.rs`` — FIPS hash vectors (SHA-256/512, SHA3-256, BLAKE2b) -* ``[ ]`` Cross-provider conformance test (requires multiple providers) -* ``[x]`` ``cargo run -p ccc-conformance-tests`` passes (12/12 vectors, all algorithms) +* ``[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) +* ``[ ]`` RFC 7748 X25519 DH test vectors +* ``[ ]`` RFC 7748 X448 DH test vectors +* ``[ ]`` XChaCha20-Poly1305 extended-nonce vectors +* ``[x]`` ``cargo run -p ccc-conformance-tests`` passes (all current vectors) ---- -Step 8 — Architecture Documentation +Step 5 — Architecture Documentation -------------------------------------- * ``[ ]`` Create ``docs/phase4_rust_architecture.rst`` * ``[ ]`` Crate dependency graph (ASCII diagram) * ``[ ]`` "How to add a new provider" — 7-step trait checklist * ``[ ]`` ``algo: u32`` → cipher constant mapping table -* ``[ ]`` Phase 8 stretch-goal provider list documented +* ``[ ]`` Milestone 2 hand-off contract documented ---- -Final Verification Gate ------------------------- +Milestone 1 Verification Gate +------------------------------ -* ``[x]`` ``cargo test --workspace`` — all pass (8/8 unit + 12/12 conformance) +*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 * ``[ ]`` ``cargo build --target aarch64-apple-ios`` — success * ``[ ]`` ``cargo build --target aarch64-linux-android`` — success -* ``[ ]`` Flutter roundtrip integration test passes (1 KB encrypt/decrypt) -* ``[ ]`` ``CccSelfTest.runAll()`` all-pass in app debug screen -* ``[ ]`` Cross-provider conformance confirmed (``deterministic_io: true`` - verified for AES-256-GCM and ChaCha20-Poly1305) +* ``[ ]`` No ``flutter_rust_bridge`` / Dart / Flutter dependency in workspace +* ``[ ]`` ``cargo audit`` — no known CVEs ---- -Phase 8 — Stretch Goal Providers (Future) ------------------------------------------- +============================================================ +Milestone 2 — ``ccc_cryptography`` Flutter Plugin +=========================================================== -*(Out of scope for Phase 4. Tracked here for future scheduling.)* +*(Not started — begins after Milestone 1 gate passes)* -* ``[ ]`` 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 +Step 1 — New Repository Setup +------------------------------- - -Legend ------- - -* ``[ ]`` Not started -* ``[~]`` In progress -* ``[x]`` Complete -* ``[!]`` Blocked +* ``[ ]`` 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`` ---- -Step 1 — Cargo Workspace Scaffold ----------------------------------- +Step 2 — Bridge Crate +---------------------- -* ``[ ]`` Create ``Cargo.toml`` (workspace manifest, 3 members) -* ``[ ]`` Create ``rust-toolchain.toml`` (stable, pinned version) -* ``[ ]`` Create ``.cargo/config.toml`` (cross-compile target aliases) -* ``[ ]`` Create ``vendors/README.md`` - ----- - -Step 2 — ``ccc-crypto-core`` Trait Crate ------------------------------------------ - -* ``[ ]`` Create ``crates/ccc-crypto-core/Cargo.toml`` -* ``[ ]`` ``algorithms.rs`` — AeadAlgorithm, KdfAlgorithm, MacAlgorithm, - HashAlgorithm, KemAlgorithm enums (values == cipher_constants.dart) -* ``[ ]`` ``capabilities.rs`` — AlgorithmCapability, ProviderCapabilities -* ``[ ]`` ``error.rs`` — CryptoError enum -* ``[ ]`` ``types.rs`` — KemKeyPair, SelfTestReport, BenchmarkReport, - AlgoTestResult -* ``[ ]`` ``provider.rs`` — AeadProvider, KdfProvider, MacProvider, - HashProvider, KemProvider traits; CryptoProvider umbrella trait -* ``[ ]`` ``registry.rs`` — ProviderRegistry (OnceLock>), - register(), get(), list() -* ``[ ]`` ``lib.rs`` — re-exports all public items -* ``[ ]`` Unit tests for registry (register, get, list) - ----- - -Step 3 — wolfSSL Submodule + ``ccc-crypto-wolfssl`` ------------------------------------------------------ - -* ``[ ]`` ``git submodule add`` wolfSSL → ``vendors/wolfssl`` -* ``[ ]`` Pin submodule to ``v5.7.2-stable`` -* ``[ ]`` Document pin in ``vendors/README.md`` -* ``[ ]`` Create ``crates/ccc-crypto-wolfssl/Cargo.toml`` -* ``[ ]`` ``aead.rs`` — AES-256-GCM implementation - - * ``[ ]`` encrypt_aead (AES-256-GCM) - * ``[ ]`` decrypt_aead (AES-256-GCM) - * ``[ ]`` encrypt_aead (ChaCha20-Poly1305) - * ``[ ]`` decrypt_aead (ChaCha20-Poly1305) - -* ``[ ]`` ``kdf.rs`` — KDF implementations - - * ``[ ]`` HKDF-SHA256 - * ``[ ]`` HKDF-SHA384 - * ``[ ]`` HKDF-SHA512 - * ``[ ]`` Argon2id - -* ``[ ]`` ``mac.rs`` — MAC implementations - - * ``[ ]`` HMAC-SHA256 - * ``[ ]`` HMAC-SHA384 - * ``[ ]`` HMAC-SHA512 - -* ``[ ]`` ``hash.rs`` — Hash implementations - - * ``[ ]`` SHA-256 / SHA-384 / SHA-512 - * ``[ ]`` SHA3-256 / SHA3-512 - * ``[ ]`` BLAKE2b-512 - -* ``[ ]`` ``kem.rs`` — KEM implementations - - * ``[ ]`` X25519 - * ``[ ]`` X448 - * ``[ ]`` ML-KEM-768 (conditional on PQ build) - * ``[ ]`` ML-KEM-1024 (conditional on PQ build) - -* ``[ ]`` ``capabilities.rs`` — probe-at-startup per algorithm -* ``[ ]`` ``capabilities.rs`` — benchmark() throughput micro-bench -* ``[ ]`` ``provider.rs`` — WolfSslProvider: CryptoProvider impl -* ``[ ]`` ``provider.rs`` — self_test() with embedded NIST vectors -* ``[ ]`` Register WolfSslProvider in ProviderRegistry via init() -* ``[ ]`` Unit tests for each implemented algorithm - ----- - -Step 4 — ``ccc-flutter-bridge`` Entry-Point Crate ---------------------------------------------------- - -* ``[ ]`` Create ``crates/ccc-flutter-bridge/Cargo.toml`` -* ``[ ]`` Set ``crate-type = ["cdylib", "staticlib"]`` -* ``[ ]`` Add ``flutter_rust_bridge`` dependency * ``[ ]`` ``dto.rs`` — CapabilitiesDto, KemKeyPairDto, KemEncapDto, - SelfTestDto, AlgoTestResultDto + SelfTestDto, AlgoTestResultDto; From impls * ``[ ]`` ``bridge.rs`` — ccc_init() * ``[ ]`` ``bridge.rs`` — ccc_list_providers() -* ``[ ]`` ``bridge.rs`` — ccc_provider_capabilities() +* ``[ ]`` ``bridge.rs`` — ccc_capabilities() / ccc_available_algorithms() * ``[ ]`` ``bridge.rs`` — ccc_aead_encrypt() / ccc_aead_decrypt() -* ``[ ]`` ``bridge.rs`` — ccc_derive_key() -* ``[ ]`` ``bridge.rs`` — ccc_compute_mac() / ccc_verify_mac() +* ``[ ]`` ``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() -* ``[ ]`` ``lib.rs`` — frb_generated module import ---- -Step 5 — Flutter Build Integration ------------------------------------- - -* ``[ ]`` Add ``flutter_rust_bridge: ^2`` to ``pubspec.yaml`` -* ``[ ]`` Run ``flutter_rust_bridge_codegen generate`` -* ``[ ]`` Verify generated ``flutter_src/ccc_crypto_bindings/ccc_crypto.dart`` -* ``[ ]`` iOS plugin scaffold (``ios/`` dir, cargokit integration) -* ``[ ]`` Android plugin scaffold (``android/`` dir, CMakeLists.txt) -* ``[ ]`` macOS plugin scaffold (``macos/`` dir) -* ``[ ]`` Confirm ``flutter build ios`` succeeds (static lib linked) -* ``[ ]`` Confirm ``flutter build apk`` succeeds (cdylib linked) - ----- - -Step 6 — Dart Layer Wiring ---------------------------- - -* ``[ ]`` Wire ``crypto_wolfssl.dart`` ``encrypt()`` → ``ccc_aead_encrypt()`` -* ``[ ]`` Wire ``crypto_wolfssl.dart`` ``decrypt()`` → ``ccc_aead_decrypt()`` -* ``[ ]`` Convert ``CccProviderCatalog.capabilities`` to runtime-populated map -* ``[ ]`` Call ``ccc_init()`` at app startup -* ``[ ]`` Populate ``CccProviderCatalog`` from ``ccc_provider_capabilities()`` -* ``[ ]`` Create ``CccSelfTest`` Dart class (wraps ``ccc_self_test()``) -* ``[ ]`` Expose self-test pass/fail diagnostics in app debug screen - ----- - -Step 7 — Conformance Test Suite +Step 3 — Codegen + Plugin Build --------------------------------- -* ``[ ]`` ``tests/conformance/aes_gcm_vectors.rs`` — NIST SP 800-38D vectors -* ``[ ]`` ``tests/conformance/chacha_vectors.rs`` — RFC 8439 vectors -* ``[ ]`` ``tests/conformance/hkdf_vectors.rs`` — RFC 5869 vectors -* ``[ ]`` ``tests/conformance/hmac_vectors.rs`` — RFC 4231 vectors -* ``[ ]`` ``tests/conformance/cross_provider.rs`` — wolfSSL output matches - Dart ``cryptography`` reference output (byte-identity) -* ``[ ]`` ``cargo test --workspace`` all pass +* ``[ ]`` 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 ---- -Step 8 — Architecture Documentation --------------------------------------- - -* ``[ ]`` Create ``docs/phase4_rust_architecture.rst`` -* ``[ ]`` Crate dependency graph (ASCII diagram) -* ``[ ]`` "How to add a new provider" — 7-step trait checklist -* ``[ ]`` ``algo: u32`` → cipher constant mapping table -* ``[ ]`` Phase 8 stretch-goal provider list documented - ----- - -Final Verification Gate +Step 4 — Dart API Layer ------------------------ -* ``[ ]`` ``cargo test --workspace`` — all pass -* ``[ ]`` ``cargo build --target aarch64-apple-ios`` — success -* ``[ ]`` ``cargo build --target aarch64-linux-android`` — success -* ``[ ]`` Flutter roundtrip integration test passes (1 KB encrypt/decrypt) -* ``[ ]`` ``CccSelfTest.runAll()`` all-pass in app debug screen -* ``[ ]`` Cross-provider conformance confirmed (``deterministic_io: true`` - verified for AES-256-GCM and ChaCha20-Poly1305) +* ``[ ]`` ``CccCrypto`` class (wraps all bridge calls) +* ``[ ]`` ``CccSelfTest`` class (wraps ccc_self_test()) +* ``[ ]`` ``CccProviderCatalog`` (runtime-populated from ccc_capabilities()) + +---- + +Step 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) ---- diff --git a/flutter_rust_bridge.yaml b/flutter_rust_bridge.yaml deleted file mode 100644 index 3d1071e..0000000 --- a/flutter_rust_bridge.yaml +++ /dev/null @@ -1,24 +0,0 @@ -# flutter_rust_bridge v2.11.1 codegen configuration -# Run from the ccc_rust/ workspace root: -# flutter_rust_bridge_codegen generate -# -# All paths are relative to this file (the workspace root). - -# Crate directory containing the bridge Cargo.toml. -rust_root: "crates/ccc-flutter-bridge" - -# Module paths within the crate that expose #[frb] functions. -# Comma-separated, using Rust module path syntax. -rust_input: "crate::bridge,crate::dto" - -# Where to write the generated Dart bindings. -dart_output: "../letusmsg_app/flutter_src/lib/gen/rust" - -# Where to write the generated Rust glue (frb_generated.rs). -rust_output: "crates/ccc-flutter-bridge/src/frb_generated.rs" - -# C header for iOS/macOS static-lib linkage. -c_output: "crates/ccc-flutter-bridge/include/ccc_bridge.h" - -# Dart class name exposed to the Flutter app. -dart_entrypoint_class_name: "CccCrypto" diff --git a/flutter_src/ccc/attachment_crypto_context.dart b/flutter_src/ccc/attachment_crypto_context.dart deleted file mode 100644 index 9b38fa3..0000000 --- a/flutter_src/ccc/attachment_crypto_context.dart +++ /dev/null @@ -1,17 +0,0 @@ -/// Attachment crypto context for BG attachment read/write operations. -/// -/// This data container carries the resolved channel cipher sequence and the -/// key-schedule-enriched cipher parameters so attachment crypto calls can use -/// one consistent context. -class AttachmentCryptoContext { - /// Ordered cipher chain applied by CCC for this attachment operation. - final List cipherSequence; - - /// Effective cipher parameters, including key-schedule metadata. - final Map cipherParams; - - const AttachmentCryptoContext({ - required this.cipherSequence, - required this.cipherParams, - }); -} diff --git a/flutter_src/ccc/ccc_channel_profile.dart b/flutter_src/ccc/ccc_channel_profile.dart deleted file mode 100644 index bda74bc..0000000 --- a/flutter_src/ccc/ccc_channel_profile.dart +++ /dev/null @@ -1,321 +0,0 @@ -/// -/// Channel-level CCC profile derivation. -/// -import 'package:letusmsg/ccc/ccc_kdf.dart'; -import 'package:letusmsg/ccc/cipher_constants.dart'; -import 'package:letusmsg/ccc/ccc_provider_spec.dart'; -import 'package:letusmsg/data/ccc_data.dart'; - -/// One resolved cipher execution step for a channel CCC route. -/// -/// The step identifies a primary provider and optional ordered fallbacks. -class CccRouteStep { - final int cipher; - final CccCryptoProvider provider; - final List fallbackProviders; - - const CccRouteStep({ - required this.cipher, - required this.provider, - required this.fallbackProviders, - }); - - Map toMap() { - return { - 'cipher': cipher, - 'provider': provider.name, - 'fallbackProviders': fallbackProviders.map((item) => item.name).toList(growable: false), - }; - } -} - -/// Concrete cipher configuration derived from per-channel `CCCData`. -class ChannelCccProfile { - final int combo; - final int iterations; - final CccExecutionMode executionMode; - final bool allowFallback; - final List providers; - final List route; - final List cipherSequence; - final Map cipherParams; - - const ChannelCccProfile({ - required this.combo, - required this.iterations, - required this.executionMode, - required this.allowFallback, - required this.providers, - required this.route, - required this.cipherSequence, - required this.cipherParams, - }); - - static const int _maxIterations = 16; - - factory ChannelCccProfile.fromCccData(CCCData? cccData) { - final combo = cccData?.combo ?? 0; - final rawIterations = cccData?.iterrations ?? 0; - final kdfFunctionValue = normalizeCccKdfFunctionValue(cccData?.kdfFunction); - final kdfFunction = cccKdfFunctionFromInt(kdfFunctionValue); - final executionMode = cccExecutionModeFromString(cccData?.executionMode ?? 'auto'); - final iterations = rawIterations <= 0 - ? 1 - : rawIterations.clamp(1, _maxIterations); - final allowFallback = executionMode != CccExecutionMode.strict; - - final providers = _providersForCombo(combo); - final route = _resolveRoute(providers, executionMode: executionMode, allowFallback: allowFallback); - final baseSequence = route.map((item) => item.cipher).toList(growable: false); - final expandedSequence = []; - for (var i = 0; i < iterations; i++) { - expandedSequence.addAll(baseSequence); - } - - final params = { - ...CipherConstants.DEFAULT_CIPHER_PARAMS, - 'ccc_combo': combo, - 'ccc_iterations': iterations, - 'ccc_kdf_function': kdfFunction.name, - 'ccc_kdf_function_value': kdfFunction.value, - 'ccc_execution_mode': executionMode.name, - 'ccc_allow_fallback': allowFallback, - 'ccc_providers': providers.map((provider) => provider.toMap()).toList(growable: false), - 'ccc_route': route.map((step) => step.toMap()).toList(growable: false), - // Phase 3: length-hiding padding parameters - 'ccc_min_padding_bytes': cccData?.minPaddingBytes ?? 32, - 'ccc_block_size': cccData?.blockSize ?? 256, - }; - - return ChannelCccProfile( - combo: combo, - iterations: iterations, - executionMode: executionMode, - allowFallback: allowFallback, - providers: providers, - route: route, - cipherSequence: expandedSequence, - cipherParams: params, - ); - } - - static List _resolveRoute( - List providers, { - required CccExecutionMode executionMode, - required bool allowFallback, - }) { - final strictRoute = []; - for (final provider in providers) { - for (final cipher in provider.ciphers) { - strictRoute.add(CccRouteStep( - cipher: cipher, - provider: provider.provider, - fallbackProviders: const [], - )); - } - } - - if (executionMode == CccExecutionMode.strict) { - return strictRoute; - } - - final optimizedRoute = []; - for (final step in strictRoute) { - final ordered = _orderedProviderCandidates( - cipher: step.cipher, - configuredProviders: providers.map((item) => item.provider).toSet(), - executionMode: executionMode, - ); - - final primary = ordered.isNotEmpty ? ordered.first : step.provider; - final fallbacks = allowFallback - ? ordered.where((provider) => provider != primary).toList(growable: false) - : const []; - - optimizedRoute.add(CccRouteStep( - cipher: step.cipher, - provider: primary, - fallbackProviders: fallbacks, - )); - } - - return optimizedRoute; - } - - static List _orderedProviderCandidates({ - required int cipher, - required Set configuredProviders, - required CccExecutionMode executionMode, - }) { - final configured = configuredProviders.where((provider) { - return CccProviderCatalog.supports(provider, cipher); - }).toList(growable: false); - - if (executionMode == CccExecutionMode.efficient) { - final rankedConfigured = List.from(configured) - ..sort((a, b) { - final capA = CccProviderCatalog.capability(a, cipher); - final capB = CccProviderCatalog.capability(b, cipher); - final perf = (capB?.efficiencyScore ?? 0).compareTo(capA?.efficiencyScore ?? 0); - if (perf != 0) return perf; - return (capB?.reliabilityScore ?? 0).compareTo(capA?.reliabilityScore ?? 0); - }); - return rankedConfigured; - } - - final availableRanked = CccProviderCatalog.providersSupporting(cipher, availableOnly: true) - .where(configuredProviders.contains) - .toList(growable: false); - - final unavailableRanked = CccProviderCatalog.providersSupporting(cipher, availableOnly: false) - .where((provider) => configuredProviders.contains(provider) && !availableRanked.contains(provider)) - .toList(growable: false); - - return [ - ...availableRanked, - ...unavailableRanked, - ]; - } - - static List _providersForCombo(int combo) { - switch (combo) { - case 0: - // Combo 0 is reserved as the plaintext / unencrypted legacy combo. - // It produces an empty cipher sequence so the CCC pipeline serializes - // and deserializes JSON only, with no encryption layers applied. - // Backwards-compatible with all channels created before Normal Mode. - // When Normal Mode is complete, CCCData.blank() will be updated to a - // real encrypted combo (e.g. combo 5 or higher) and combo 0 will - // remain available only for migration/legacy channels. - return []; - - case 1: - return [ - CccProviderSpec( - provider: CccCryptoProvider.wolfssl, - ciphers: [ - CipherConstants.AES_GCM_256, - CipherConstants.CHACHA20_POLY1305, - ], - ), - CccProviderSpec( - provider: CccCryptoProvider.cryptography, - ciphers: [ - CipherConstants.HMAC_SHA512, - CipherConstants.BLAKE2B, - ], - ), - ]; - case 2: - return [ - CccProviderSpec( - provider: CccCryptoProvider.boringssl, - ciphers: [ - CipherConstants.CHACHA20_POLY1305, - CipherConstants.XCHACHA20_POLY1305, - ], - ), - CccProviderSpec( - provider: CccCryptoProvider.cryptography, - ciphers: [ - CipherConstants.AES_GCM_256, - ], - ), - ]; - case 3: - return [ - CccProviderSpec( - provider: CccCryptoProvider.openssl, - ciphers: [ - CipherConstants.AES_GCM_256, - ], - ), - CccProviderSpec( - provider: CccCryptoProvider.wolfssl, - ciphers: [ - CipherConstants.CHACHA20_POLY1305, - ], - ), - CccProviderSpec( - provider: CccCryptoProvider.cryptography, - ciphers: [ - CipherConstants.BLAKE2B, - ], - ), - ]; - case 4: - return [ - CccProviderSpec( - provider: CccCryptoProvider.wolfssl, - ciphers: [ - CipherConstants.XCHACHA20_POLY1305, - ], - ), - CccProviderSpec( - provider: CccCryptoProvider.openssl, - ciphers: [ - CipherConstants.HMAC_SHA512, - ], - ), - CccProviderSpec( - provider: CccCryptoProvider.cryptography, - ciphers: [ - CipherConstants.BLAKE2B, - ], - ), - ]; - - // --- Basic / user-selectable combos (5-9) --- - - case 5: - // Basic: single AES-256-GCM - return [ - CccProviderSpec( - provider: CccCryptoProvider.cryptography, - ciphers: List.from(CipherConstants.BASIC_AES_SEQUENCE), - ), - ]; - case 6: - // Basic: single ChaCha20-Poly1305 - return [ - CccProviderSpec( - provider: CccCryptoProvider.cryptography, - ciphers: List.from(CipherConstants.BASIC_CHACHA_SEQUENCE), - ), - ]; - case 7: - // Basic: single XChaCha20-Poly1305 - return [ - CccProviderSpec( - provider: CccCryptoProvider.cryptography, - ciphers: List.from(CipherConstants.BASIC_XCHACHA_SEQUENCE), - ), - ]; - case 8: - // Dual AEAD: AES-256-GCM + ChaCha20-Poly1305 - return [ - CccProviderSpec( - provider: CccCryptoProvider.cryptography, - ciphers: List.from(CipherConstants.DUAL_AEAD_SEQUENCE), - ), - ]; - case 9: - // Triple AEAD: AES + ChaCha20 + XChaCha20 - return [ - CccProviderSpec( - provider: CccCryptoProvider.cryptography, - ciphers: List.from(CipherConstants.TRIPLE_AEAD_SEQUENCE), - ), - ]; - - default: - // Unknown combo falls back to standard 5-layer - return [ - CccProviderSpec( - provider: CccCryptoProvider.cryptography, - ciphers: List.from(CipherConstants.PHASE1_SEQUENCE), - ), - ]; - } - } -} diff --git a/flutter_src/ccc/ccc_iso.dart b/flutter_src/ccc/ccc_iso.dart deleted file mode 100644 index 2b5a125..0000000 --- a/flutter_src/ccc/ccc_iso.dart +++ /dev/null @@ -1,632 +0,0 @@ -/// -/// Cipher implementations for isolate workers -/// Uses cryptography package for all crypto operations -/// -import 'dart:convert'; -import 'dart:isolate'; -import 'dart:math'; -import 'dart:typed_data'; -import 'package:cryptography/cryptography.dart'; -import 'ccc_iso_operation.dart'; -import 'ccc_iso_result.dart'; -import 'cipher_constants.dart'; - -/// Main crypto worker function that runs in isolates -@pragma('vm:entry-point') -Future> cryptoWorkerFunction(Map data) async { - final startTime = DateTime.now(); - - // Use isolate hash code as a stable worker identifier - final isolateHash = Isolate.current.hashCode.abs() % 10000; - final workerId = 'isolate_$isolateHash'; - - try { - // Deserialize operation - final operation = CryptoOperation.fromMap(data); - - // Execute cipher chain - final resultData = await _executeCipherChain( - operation.data, - operation.cipherSequence, - operation.params, - operation.type, - ); - - final processingTime = DateTime.now().difference(startTime); - - // Create success result - final result = CryptoResult.success( - operationId: operation.id, - data: resultData, - processingTime: processingTime, - workerId: workerId, - ); - - return result.toMap(); - } catch (error, stackTrace) { - final processingTime = DateTime.now().difference(startTime); - - // Create error result - final result = CryptoResult.error( - operationId: data['id'] as String? ?? 'unknown', - error: error.toString(), - stackTrace: stackTrace.toString(), - processingTime: processingTime, - workerId: workerId, - ); - - return result.toMap(); - } -} - -/// Execute cipher chain based on operation type -Future> _executeCipherChain(List inputData, List cipherSequence, - Map params, OperationType operationType) async { - List data = inputData; - final associatedData = _buildAssociatedDataBytes(params); - - if (operationType == OperationType.encrypt) { - // Apply length-hiding padding before encryption - data = _applyPadding(data, params); - - // Forward execution for encryption - for (var i = 0; i < cipherSequence.length; i++) { - data = await _executeCipher( - data, - cipherSequence[i], - params, - true, - associatedData: associatedData, - layerIndex: i, - ); - } - } else { - // Reverse execution for decryption — peel outermost layer first - for (var i = cipherSequence.length - 1; i >= 0; i--) { - data = await _executeCipher( - data, - cipherSequence[i], - params, - false, - associatedData: associatedData, - layerIndex: i, - ); - } - - // Strip length-hiding padding after decryption - data = _stripPadding(data); - } - - return data; -} - -/// Execute single cipher operation. -/// -/// [layerIndex] identifies this step's position in the cipher sequence. -/// Combined with [cipherConstant], it allows deterministic per-layer key -/// derivation when `phase1_root_key_b64` is present in [params]. -Future> _executeCipher(List data, int cipherConstant, - Map params, bool isEncrypt, - {List? associatedData, int layerIndex = 0}) async { - switch (cipherConstant) { - // Key Derivation Functions - case CipherConstants.ARGON2ID: - return await _executeArgon2id(data, params); - - // AEAD Ciphers - case CipherConstants.AES_GCM_256: - return await _executeAesGcm256(data, params, isEncrypt, - associatedData: associatedData, layerIndex: layerIndex); - case CipherConstants.CHACHA20_POLY1305: - return await _executeChacha20Poly1305(data, params, isEncrypt, - associatedData: associatedData, layerIndex: layerIndex); - case CipherConstants.XCHACHA20_POLY1305: - return await _executeXChacha20Poly1305(data, params, isEncrypt, - associatedData: associatedData, layerIndex: layerIndex); - - // MAC Algorithms - case CipherConstants.HMAC_SHA512: - return await _executeHmacSha512(data, params, isEncrypt, layerIndex: layerIndex); - case CipherConstants.BLAKE2B: - return await _executeBlake2b(data, params, isEncrypt); - - default: - throw UnsupportedError('Cipher not implemented: ${CipherConstants.getCipherName(cipherConstant)}'); - } -} - -/// Argon2id key derivation (always applied, regardless of encrypt/decrypt) -Future> _executeArgon2id(List data, Map params) async { - final algorithm = Argon2id( - memory: params['argon2_memory'] as int? ?? 64 * 1024, - parallelism: params['argon2_parallelism'] as int? ?? 4, - iterations: params['argon2_iterations'] as int? ?? 3, - hashLength: params['argon2_hash_length'] as int? ?? 32, - ); - - // Use first 16 bytes as salt, or generate if data is too short - Uint8List salt; - if (data.length >= 16) { - salt = Uint8List.fromList(data.take(16).toList()); - } else { - salt = Uint8List.fromList(List.generate(16, (i) => i)); - } - - final secretKey = await algorithm.deriveKeyFromPassword( - password: String.fromCharCodes(data), - nonce: salt.toList(), - ); - - final keyBytes = await secretKey.extractBytes(); - return keyBytes; -} - -/// AES-256-GCM encryption/decryption. -/// -/// When `phase1_root_key_b64` is present in [params], derives a deterministic -/// per-layer key from the channel root key (real E2E encryption). -/// Output format: `[12B nonce][ciphertext][16B MAC]`. -/// -/// Legacy mode (no root key): generates a random key per encryption and -/// embeds it in the output: `[32B key][12B nonce][ciphertext][16B MAC]`. -Future> _executeAesGcm256( - List data, - Map params, - bool isEncrypt, { - List? associatedData, - int layerIndex = 0, -}) async { - final algorithm = AesGcm.with256bits(); - final useDerivedKey = params.containsKey('phase1_root_key_b64'); - - if (isEncrypt) { - final SecretKey secretKey; - if (useDerivedKey) { - final keyBytes = await _deriveLayerKey(params, layerIndex, CipherConstants.AES_GCM_256, 32); - secretKey = SecretKeyData(keyBytes); - } else { - secretKey = await algorithm.newSecretKey(); - } - - final secretBox = await algorithm.encrypt( - data, - secretKey: secretKey, - aad: associatedData ?? const [], - ); - - if (useDerivedKey) { - // Derived-key format: [nonce][ciphertext][mac] - return [...secretBox.nonce, ...secretBox.cipherText, ...secretBox.mac.bytes]; - } - // Legacy format: [key][nonce][ciphertext][mac] - final keyBytes = await secretKey.extractBytes(); - return [...keyBytes, ...secretBox.nonce, ...secretBox.cipherText, ...secretBox.mac.bytes]; - } else { - if (useDerivedKey) { - // Derived-key format: [12B nonce][ciphertext][16B mac] - if (data.length < 12 + 16) { - throw ArgumentError('Invalid AES-GCM derived-key data length'); - } - final keyBytes = await _deriveLayerKey(params, layerIndex, CipherConstants.AES_GCM_256, 32); - final nonce = data.sublist(0, 12); - final cipherText = data.sublist(12, data.length - 16); - final macBytes = data.sublist(data.length - 16); - return await algorithm.decrypt( - SecretBox(cipherText, nonce: nonce, mac: Mac(macBytes)), - secretKey: SecretKeyData(keyBytes), - aad: associatedData ?? const [], - ); - } - // Legacy format: [32B key][12B nonce][ciphertext][16B mac] - if (data.length < 32 + 12 + 16) { - throw ArgumentError('Invalid AES-GCM data length'); - } - final keyBytes = data.sublist(0, 32); - final nonce = data.sublist(32, 44); - final cipherText = data.sublist(44, data.length - 16); - final macBytes = data.sublist(data.length - 16); - return await algorithm.decrypt( - SecretBox(cipherText, nonce: nonce, mac: Mac(macBytes)), - secretKey: SecretKeyData(keyBytes), - aad: associatedData ?? const [], - ); - } -} - -/// ChaCha20-Poly1305 encryption/decryption. -/// -/// Derived-key output: `[12B nonce][ciphertext][16B MAC]`. -/// Legacy output: `[32B key][12B nonce][ciphertext][16B MAC]`. -Future> _executeChacha20Poly1305( - List data, - Map params, - bool isEncrypt, { - List? associatedData, - int layerIndex = 0, -}) async { - final algorithm = Chacha20.poly1305Aead(); - final useDerivedKey = params.containsKey('phase1_root_key_b64'); - - if (isEncrypt) { - final SecretKey secretKey; - if (useDerivedKey) { - final keyBytes = await _deriveLayerKey(params, layerIndex, CipherConstants.CHACHA20_POLY1305, 32); - secretKey = SecretKeyData(keyBytes); - } else { - secretKey = await algorithm.newSecretKey(); - } - - final secretBox = await algorithm.encrypt( - data, - secretKey: secretKey, - aad: associatedData ?? const [], - ); - - if (useDerivedKey) { - return [...secretBox.nonce, ...secretBox.cipherText, ...secretBox.mac.bytes]; - } - final keyBytes = await secretKey.extractBytes(); - return [...keyBytes, ...secretBox.nonce, ...secretBox.cipherText, ...secretBox.mac.bytes]; - } else { - if (useDerivedKey) { - if (data.length < 12 + 16) { - throw ArgumentError('Invalid ChaCha20-Poly1305 derived-key data length'); - } - final keyBytes = await _deriveLayerKey(params, layerIndex, CipherConstants.CHACHA20_POLY1305, 32); - final nonce = data.sublist(0, 12); - final cipherText = data.sublist(12, data.length - 16); - final macBytes = data.sublist(data.length - 16); - return await algorithm.decrypt( - SecretBox(cipherText, nonce: nonce, mac: Mac(macBytes)), - secretKey: SecretKeyData(keyBytes), - aad: associatedData ?? const [], - ); - } - if (data.length < 32 + 12 + 16) { - throw ArgumentError('Invalid ChaCha20-Poly1305 data length'); - } - final keyBytes = data.sublist(0, 32); - final nonce = data.sublist(32, 44); - final cipherText = data.sublist(44, data.length - 16); - final macBytes = data.sublist(data.length - 16); - return await algorithm.decrypt( - SecretBox(cipherText, nonce: nonce, mac: Mac(macBytes)), - secretKey: SecretKeyData(keyBytes), - aad: associatedData ?? const [], - ); - } -} - -/// XChaCha20-Poly1305 encryption/decryption. -/// -/// Derived-key output: `[24B nonce][ciphertext][16B MAC]`. -/// Legacy output: `[32B key][24B nonce][ciphertext][16B MAC]`. -Future> _executeXChacha20Poly1305( - List data, - Map params, - bool isEncrypt, { - List? associatedData, - int layerIndex = 0, -}) async { - final algorithm = Xchacha20.poly1305Aead(); - final useDerivedKey = params.containsKey('phase1_root_key_b64'); - - if (isEncrypt) { - final SecretKey secretKey; - if (useDerivedKey) { - final keyBytes = await _deriveLayerKey(params, layerIndex, CipherConstants.XCHACHA20_POLY1305, 32); - secretKey = SecretKeyData(keyBytes); - } else { - secretKey = await algorithm.newSecretKey(); - } - - final secretBox = await algorithm.encrypt( - data, - secretKey: secretKey, - aad: associatedData ?? const [], - ); - - if (useDerivedKey) { - return [...secretBox.nonce, ...secretBox.cipherText, ...secretBox.mac.bytes]; - } - final keyBytes = await secretKey.extractBytes(); - return [...keyBytes, ...secretBox.nonce, ...secretBox.cipherText, ...secretBox.mac.bytes]; - } else { - if (useDerivedKey) { - if (data.length < 24 + 16) { - throw ArgumentError('Invalid XChaCha20-Poly1305 derived-key data length'); - } - final keyBytes = await _deriveLayerKey(params, layerIndex, CipherConstants.XCHACHA20_POLY1305, 32); - final nonce = data.sublist(0, 24); - final cipherText = data.sublist(24, data.length - 16); - final macBytes = data.sublist(data.length - 16); - return await algorithm.decrypt( - SecretBox(cipherText, nonce: nonce, mac: Mac(macBytes)), - secretKey: SecretKeyData(keyBytes), - aad: associatedData ?? const [], - ); - } - if (data.length < 32 + 24 + 16) { - throw ArgumentError('Invalid XChaCha20-Poly1305 data length'); - } - final keyBytes = data.sublist(0, 32); - final nonce = data.sublist(32, 56); - final cipherText = data.sublist(56, data.length - 16); - final macBytes = data.sublist(data.length - 16); - return await algorithm.decrypt( - SecretBox(cipherText, nonce: nonce, mac: Mac(macBytes)), - secretKey: SecretKeyData(keyBytes), - aad: associatedData ?? const [], - ); - } -} - -/// Build canonical associated-data bytes from Phase 1 params. -/// -/// The worker expects `phase1_associated_data` in params and canonicalizes it -/// to stable UTF-8 JSON so encrypt/decrypt use identical AEAD AAD bytes. -/// -/// Phase 1 exclusions (both removed so sender/receiver produce identical AD): -/// - `direction`: sender uses 'out', receiver uses 'in' for the same ciphertext. -/// - `message_sequence`: sender encrypts before the relay assigns server_seq, -/// so the receiver's relay-assigned sequence would mismatch. Sequence binding -/// will be re-enabled in Phase 2 when the ratchet provides agreed-upon counters. -List? _buildAssociatedDataBytes(Map params) { - final phase1 = params['phase1_associated_data']; - if (phase1 == null) return null; - - final canonical = _canonicalizeJsonSafe(phase1); - if (canonical == null) return null; - - if (canonical is Map) { - final normalized = Map.from(canonical) - ..remove('direction') - ..remove('message_sequence'); - return utf8.encode(jsonEncode(normalized)); - } - - if (canonical is List) { - return utf8.encode(jsonEncode(canonical)); - } - - return utf8.encode(canonical.toString()); -} - -dynamic _canonicalizeJsonSafe(dynamic value) { - if (value is Map) { - final keys = value.keys.map((item) => item.toString()).toList()..sort(); - final normalized = {}; - for (final key in keys) { - normalized[key] = _canonicalizeJsonSafe(value[key]); - } - return normalized; - } - - if (value is List) { - return value.map(_canonicalizeJsonSafe).toList(growable: false); - } - - return value; -} - -// --------------------------------------------------------------------------- -// Derived-key helpers -// --------------------------------------------------------------------------- - -/// Derive a deterministic per-layer encryption key from the channel root key. -/// -/// Uses SHA-512 (always, regardless of channel KDF selection) to ensure -/// sufficient output length for all cipher types: -/// - AEAD ciphers (AES-256-GCM, ChaCha20, XChaCha20): 32 bytes -/// - HMAC-SHA512: 64 bytes -/// -/// The derivation is deterministic: identical inputs on sender and receiver -/// produce the same key, enabling real E2E encryption without embedding keys -/// in the ciphertext. -/// -/// Formula: `SHA-512(rootKeyBytes || "|lk|{layerIndex}|c|{cipherConstant}")` -/// truncated to [keyLength] bytes. -Future> _deriveLayerKey( - Map params, - int layerIndex, - int cipherConstant, - int keyLength, -) async { - final rootKeyB64 = params['phase1_root_key_b64'] as String; - final rootKeyBytes = _decodeBase64UrlNoPad(rootKeyB64); - - // Derive: SHA-512(rootKey || domain-separation-label) - final input = [ - ...rootKeyBytes, - ...utf8.encode('|lk|$layerIndex|c|$cipherConstant'), - ]; - final hash = await Sha512().hash(input); - return hash.bytes.sublist(0, keyLength); -} - -/// Decode a base64url string that may lack padding characters. -List _decodeBase64UrlNoPad(String encoded) { - final padded = encoded + '=' * ((4 - encoded.length % 4) % 4); - return base64Url.decode(padded); -} - -/// Constant-time MAC/hash comparison to prevent timing side-channels. -void _verifyMacBytes(List expected, List computed) { - if (expected.length != computed.length) { - throw ArgumentError('MAC verification failed'); - } - int diff = 0; - for (int i = 0; i < expected.length; i++) { - diff |= expected[i] ^ computed[i]; - } - if (diff != 0) { - throw ArgumentError('MAC verification failed'); - } -} - -/// HMAC-SHA512 authentication/verification. -/// -/// Derived-key output: `[data][64B MAC]`. -/// Legacy output: `[64B key][data][64B MAC]`. -Future> _executeHmacSha512(List data, Map params, bool isEncrypt, - {int layerIndex = 0}) async { - final algorithm = Hmac.sha512(); - final useDerivedKey = params.containsKey('phase1_root_key_b64'); - - if (isEncrypt) { - final SecretKey secretKey; - final List? legacyKeyBytes; - if (useDerivedKey) { - final keyBytes = await _deriveLayerKey(params, layerIndex, CipherConstants.HMAC_SHA512, 64); - secretKey = SecretKeyData(keyBytes); - legacyKeyBytes = null; - } else { - final keyBytes = List.generate(64, (i) => DateTime.now().microsecond % 256); - secretKey = SecretKeyData(keyBytes); - legacyKeyBytes = keyBytes; - } - - final mac = await algorithm.calculateMac(data, secretKey: secretKey); - - if (useDerivedKey) { - // Derived-key format: [data][mac] - return [...data, ...mac.bytes]; - } - // Legacy format: [key][data][mac] - return [...legacyKeyBytes!, ...data, ...mac.bytes]; - } else { - if (useDerivedKey) { - // Derived-key format: [data][64B mac] - if (data.length < 64) { - throw ArgumentError('Invalid HMAC-SHA512 derived-key data length'); - } - final macBytes = data.sublist(data.length - 64); - final originalData = data.sublist(0, data.length - 64); - final keyBytes = await _deriveLayerKey(params, layerIndex, CipherConstants.HMAC_SHA512, 64); - final computedMac = await algorithm.calculateMac(originalData, secretKey: SecretKeyData(keyBytes)); - _verifyMacBytes(macBytes, computedMac.bytes); - return originalData; - } - // Legacy format: [64B key][data][64B mac] - if (data.length < 64 + 64) { - throw ArgumentError('Invalid HMAC-SHA512 data length'); - } - final keyBytes = data.sublist(0, 64); - final macBytes = data.sublist(data.length - 64); - final originalData = data.sublist(64, data.length - 64); - final computedMac = await algorithm.calculateMac(originalData, secretKey: SecretKeyData(keyBytes)); - _verifyMacBytes(macBytes, computedMac.bytes); - return originalData; - } -} - -/// BLAKE2b hashing/verification (keyless integrity check). -Future> _executeBlake2b(List data, Map params, bool isEncrypt) async { - final algorithm = Blake2b(); - - if (isEncrypt) { - final hash = await algorithm.hash(data); - return [...data, ...hash.bytes]; - } else { - if (data.length < 64) { - throw ArgumentError('Invalid BLAKE2b data length'); - } - - final hashBytes = data.sublist(data.length - 64); - final originalData = data.sublist(0, data.length - 64); - final computedHash = await algorithm.hash(originalData); - _verifyMacBytes(hashBytes, computedHash.bytes); - return originalData; - } -} - -// --------------------------------------------------------------------------- -// Length-Hiding Padding (Phase 3) -// --------------------------------------------------------------------------- - -/// Default minimum random padding bytes. -const int _paddingDefaultMinBytes = 32; - -/// Default block size for length-hiding alignment. -const int _paddingDefaultBlockSize = 256; - -/// Apply length-hiding padding to plaintext before encryption. -/// -/// Format: `[plaintext][random_padding][4-byte padding_length_LE]` -/// -/// The padding ensures: -/// 1. At least [minPaddingBytes] random bytes are appended (defeats exact -/// length correlation even for known plaintexts). -/// 2. The total padded length is rounded up to the next multiple of -/// [blockSize] (groups all messages into fixed-size buckets so an -/// eavesdropper cannot distinguish "hi" from "hey"). -/// -/// The last 4 bytes always store the total padding length as a little-endian -/// uint32, allowing deterministic stripping on the receiver side. -/// -/// When both `ccc_min_padding_bytes` and `ccc_block_size` are absent from -/// [params] (legacy channels), padding is still applied with conservative -/// defaults (32B min, 256B block) so all new encryptions are length-hidden. -List _applyPadding(List plaintext, Map params) { - final minPadding = (params['ccc_min_padding_bytes'] as int?) ?? _paddingDefaultMinBytes; - final blockSize = (params['ccc_block_size'] as int?) ?? _paddingDefaultBlockSize; - - // 4 bytes reserved for the padding-length trailer - const trailerSize = 4; - - // Minimum total size: plaintext + minPadding + trailer - final minTotal = plaintext.length + minPadding + trailerSize; - - // Round up to next block boundary (block size of 0 or 1 means no alignment) - final effectiveBlock = blockSize > 1 ? blockSize : 1; - final paddedTotal = ((minTotal + effectiveBlock - 1) ~/ effectiveBlock) * effectiveBlock; - - // Total padding = everything after plaintext - final totalPadding = paddedTotal - plaintext.length; - - // Fill random padding bytes (all except last 4 which are the trailer) - final rng = Random.secure(); - final randomLen = totalPadding - trailerSize; - final randomBytes = List.generate(randomLen, (_) => rng.nextInt(256)); - - // Encode totalPadding as 4-byte little-endian - final trailer = [ - totalPadding & 0xFF, - (totalPadding >> 8) & 0xFF, - (totalPadding >> 16) & 0xFF, - (totalPadding >> 24) & 0xFF, - ]; - - return [...plaintext, ...randomBytes, ...trailer]; -} - -/// Strip length-hiding padding after decryption. -/// -/// Reads the 4-byte little-endian trailer at the end of [paddedData] to -/// determine how many bytes of padding to remove. -/// -/// Throws [ArgumentError] if the trailer claims a padding length larger than -/// the data itself (corruption or tamper indicator — the AEAD layer should -/// already have caught tampering, but defense-in-depth). -List _stripPadding(List paddedData) { - const trailerSize = 4; - if (paddedData.length < trailerSize) { - // Data too short to contain a padding trailer — return as-is for - // backward compatibility with pre-Phase-3 messages that have no padding. - return paddedData; - } - - final len = paddedData.length; - final totalPadding = paddedData[len - 4] | - (paddedData[len - 3] << 8) | - (paddedData[len - 2] << 16) | - (paddedData[len - 1] << 24); - - // Sanity: padding must be at least trailerSize and at most the full data - if (totalPadding < trailerSize || totalPadding > len) { - // Not a padded message (pre-Phase-3 legacy) — return unchanged. - return paddedData; - } - - return paddedData.sublist(0, len - totalPadding); -} diff --git a/flutter_src/ccc/ccc_iso_manager.dart b/flutter_src/ccc/ccc_iso_manager.dart deleted file mode 100644 index 602155c..0000000 --- a/flutter_src/ccc/ccc_iso_manager.dart +++ /dev/null @@ -1,247 +0,0 @@ -/// -/// Crypto Isolate Manager -/// Manages worker pool for encryption/decryption operations -/// -import 'dart:async'; -import 'package:worker_manager/worker_manager.dart'; -import 'ccc_iso_operation.dart'; -import 'ccc_iso_result.dart'; -import 'ccc_iso_operation_id.dart'; -import 'ccc_iso.dart'; -import 'cipher_constants.dart'; - -/// Manages isolate workers for cryptographic operations -/// -/// CCC (Copius Cipher Chain) Architecture: -/// - Single encryption system for ALL data (messages, attachments, thumbnails) -/// - Uses channel UUID for key derivation scope -/// - Same key encrypts message + its attachments (bundled together) -/// - Used for both over-the-wire AND local storage encryption -/// -/// FUTURE WORK: Ratchet System -/// - Per-message key derivation using Double Ratchet algorithm -/// - Keys derived from: channelUuid + messageSequence + rootKey -/// - Forward secrecy: compromise of one key doesn't reveal past messages -/// - Break-in recovery: new keys derived after compromise -/// -/// Current State: Full CCC encryption with isolate workers -/// Future: Ratchet key derivation integration -class CryptoIsolateManager { - // Performance tracking - final CryptoMetrics _metrics = CryptoMetrics(); - - // Configuration - static const Duration OPERATION_TIMEOUT = Duration(seconds: 30); - static const int WORKER_POOL_SIZE = 4; // Fixed pool of 4 workers - - bool _initialized = false; - bool _disposed = false; - - /// Initialize the crypto isolate manager - Future initialize() async { - if (_initialized) return; - - // Initialize operation ID generator - CryptoOperationId.initialize(); - - // Configure worker manager with fixed pool size - await workerManager.init(isolatesCount: WORKER_POOL_SIZE); - - _initialized = true; - } - - /// Encrypt data with specified cipher sequence - /// In passthrough mode, returns data unchanged (for development) - /// - /// [channelUuid] - Channel UUID for key derivation scope - /// [messageSequence] - Message sequence number for per-message key derivation (future: ratchet) - /// [isUserMessage] - Priority flag for worker queue - /// - /// FUTURE: When ratchet is implemented, key = derive(channelRootKey, messageSequence) - /// Same key will encrypt: MsgData + all attachment files + all thumbnails for that message - Future encrypt( - List plaintext, { - required String channelUuid, - int? messageSequence, // Future: used for ratchet key derivation - List? cipherSequence, - Map? params, - bool isUserMessage = false, - }) async { - _ensureInitialized(); - - final operation = CryptoOperation.encrypt( - plaintext: plaintext, - cipherSequence: cipherSequence ?? CipherConstants.PHASE1_SEQUENCE, - params: params ?? CipherConstants.DEFAULT_CIPHER_PARAMS, - channelUuid: channelUuid, - messageSequence: messageSequence, - isUserMessage: isUserMessage, - ); - - return await _executeOperation(operation); - } - - /// Decrypt data with specified cipher sequence - /// In passthrough mode, returns data unchanged (for development) - /// - /// [channelUuid] - Channel UUID for key derivation scope - /// [messageSequence] - Message sequence number for per-message key derivation (future: ratchet) - /// - /// FUTURE: When ratchet is implemented, key = derive(channelRootKey, messageSequence) - Future decrypt( - List ciphertext, { - required String channelUuid, - int? messageSequence, // Future: used for ratchet key derivation - List? cipherSequence, - Map? params, - }) async { - _ensureInitialized(); - - final operation = CryptoOperation.decrypt( - ciphertext: ciphertext, - cipherSequence: cipherSequence ?? CipherConstants.PHASE1_SEQUENCE, - params: params ?? CipherConstants.DEFAULT_CIPHER_PARAMS, - channelUuid: channelUuid, - messageSequence: messageSequence, - ); - - return await _executeOperation(operation); - } - - /// Execute a crypto operation - Future _executeOperation(CryptoOperation operation) async { - _ensureInitialized(); - - if (_disposed) { - throw StateError('CryptoIsolateManager has been disposed'); - } - - try { - // Execute using the global workerManager with correct API - final resultMap = await workerManager.execute>( - () => cryptoWorkerFunction(operation.toMap()), - priority: operation.priority, - ).timeout(OPERATION_TIMEOUT); - - // Deserialize result - final result = CryptoResult.fromMap(resultMap); - - // Update metrics - _updateMetrics(operation, result); - - return result; - } catch (error, stackTrace) { - // Create error result - final result = CryptoResult.error( - operationId: operation.id, - error: error.toString(), - stackTrace: stackTrace.toString(), - processingTime: operation.age, - workerId: 'manager_error', - ); - - // Update metrics - _metrics.recordError(); - - return result; - } - } - - /// Update performance metrics - void _updateMetrics(CryptoOperation operation, CryptoResult result) { - if (result.success) { - if (operation.type == OperationType.encrypt) { - _metrics.recordEncryption(result.processingTime, operation.isHighPriority); - } else { - _metrics.recordDecryption(result.processingTime); - } - } else { - _metrics.recordError(); - } - } - - /// Get current performance metrics - CryptoMetrics get metrics => _metrics; - - /// Get worker manager stats - String get workerStats { - return 'Crypto Manager Stats: ${_metrics.toString()}'; - } - - /// Check if manager is ready - bool get isReady => _initialized && !_disposed; - - /// Ensure manager is initialized - void _ensureInitialized() { - if (!_initialized) { - throw StateError('CryptoIsolateManager must be initialized before use'); - } - if (_disposed) { - throw StateError('CryptoIsolateManager has been disposed'); - } - } - - /// Dispose the isolate manager and clean up resources - Future dispose() async { - if (_disposed) return; - - _disposed = true; - - // Dispose global worker manager - try { - await workerManager.dispose(); - } catch (e) { - // Ignore disposal errors - } - - // Clear metrics - _metrics.reset(); - } - - /// Create a test operation (for debugging) - Future testOperation({ - String testData = 'Hello, Crypto World!', - String channelUuid = 'test-channel-uuid', - }) async { - final plaintext = testData.codeUnits; - - // Encrypt - final encryptResult = await encrypt( - plaintext, - channelUuid: channelUuid, - isUserMessage: true, - ); - - if (!encryptResult.success) { - return encryptResult; - } - - // Decrypt - final decryptResult = await decrypt( - encryptResult.data, - channelUuid: channelUuid, - ); - - if (!decryptResult.success) { - return decryptResult; - } - - // Verify roundtrip - final decryptedText = String.fromCharCodes(decryptResult.data); - if (decryptedText == testData) { - return CryptoResult.success( - operationId: 'test_roundtrip', - data: decryptResult.data, - processingTime: encryptResult.processingTime + decryptResult.processingTime, - workerId: 'test_manager', - ); - } else { - return CryptoResult.error( - operationId: 'test_roundtrip', - error: 'Roundtrip failed: expected "$testData", got "$decryptedText"', - processingTime: encryptResult.processingTime + decryptResult.processingTime, - workerId: 'test_manager', - ); - } - } -} diff --git a/flutter_src/ccc/ccc_iso_operation.dart b/flutter_src/ccc/ccc_iso_operation.dart deleted file mode 100644 index 2a3a8a5..0000000 --- a/flutter_src/ccc/ccc_iso_operation.dart +++ /dev/null @@ -1,190 +0,0 @@ -/// -/// Data structure for crypto operations in isolates -/// Handles serialization for isolate communication -/// -import 'package:worker_manager/worker_manager.dart'; -import 'ccc_iso_operation_id.dart'; -import 'cipher_constants.dart'; - -/// Type of cryptographic operation -enum OperationType { - encrypt, - decrypt; - - @override - String toString() => name; - - static OperationType fromString(String value) { - return OperationType.values.firstWhere( - (type) => type.name == value, - orElse: () => throw ArgumentError('Invalid OperationType: $value'), - ); - } -} - -/// Cryptographic operation data for isolate workers -/// -/// Key derivation (future ratchet implementation): -/// - channelUuid: Scope for key derivation (each channel has unique root key) -/// - messageSequence: Per-message key derivation index -/// - Final key = ratchet(channelRootKey, messageSequence) -/// -/// Same derived key encrypts: MsgData + attachment files + thumbnails -class CryptoOperation { - final String id; - final List data; - final List cipherSequence; - final Map params; - final OperationType type; - final WorkPriority priority; - final String channelUuid; // Channel UUID for key derivation scope - final int? messageSequence; // Future: ratchet index for per-message key - final DateTime timestamp; - - /// Create new crypto operation with auto-generated ID - CryptoOperation({ - required this.data, - required this.cipherSequence, - required this.params, - required this.type, - required this.channelUuid, - this.messageSequence, - this.priority = WorkPriority.high, - }) : id = CryptoOperationId.generate(), - timestamp = DateTime.now(); - - /// Create crypto operation with custom ID (for testing) - CryptoOperation.withId({ - required this.id, - required this.data, - required this.cipherSequence, - required this.params, - required this.type, - required this.channelUuid, - this.messageSequence, - this.priority = WorkPriority.high, - }) : timestamp = DateTime.now(); - - /// Create operation for encryption - factory CryptoOperation.encrypt({ - required List plaintext, - required List cipherSequence, - required Map params, - required String channelUuid, - int? messageSequence, - bool isUserMessage = false, - }) { - return CryptoOperation( - data: plaintext, - cipherSequence: cipherSequence, - params: params, - type: OperationType.encrypt, - channelUuid: channelUuid, - messageSequence: messageSequence, - priority: isUserMessage ? WorkPriority.immediately : WorkPriority.high, - ); - } - - /// Create operation for decryption - factory CryptoOperation.decrypt({ - required List ciphertext, - required List cipherSequence, - required Map params, - required String channelUuid, - int? messageSequence, - }) { - return CryptoOperation( - data: ciphertext, - cipherSequence: cipherSequence, - params: params, - type: OperationType.decrypt, - channelUuid: channelUuid, - messageSequence: messageSequence, - priority: WorkPriority.high, - ); - } - - /// Serialize for isolate communication - Map toMap() { - return { - 'id': id, - 'data': data, - 'cipherSequence': cipherSequence, - 'params': params, - 'type': type.name, - 'priority': priority.index, - 'channelUuid': channelUuid, - 'messageSequence': messageSequence, - 'timestamp': timestamp.millisecondsSinceEpoch, - }; - } - - /// Deserialize from isolate communication - static CryptoOperation fromMap(Map map) { - return CryptoOperation.withId( - id: map['id'] as String, - data: List.from(map['data'] as List), - cipherSequence: List.from(map['cipherSequence'] as List), - params: Map.from(map['params'] as Map), - type: OperationType.fromString(map['type'] as String), - channelUuid: map['channelUuid'] as String, - messageSequence: map['messageSequence'] as int?, - priority: WorkPriority.values[map['priority'] as int], - ); - } - - /// Get cipher sequence as human-readable string - String get cipherSequenceDescription { - return CipherConstants.getSequenceDescription(cipherSequence); - } - - /// Validate cipher sequence - bool get hasValidCipherSequence { - return CipherConstants.isValidSequence(cipherSequence); - } - - /// Get data size in bytes - int get dataSize => data.length; - - /// Get operation age - Duration get age => DateTime.now().difference(timestamp); - - /// Check if operation is high priority - bool get isHighPriority => priority == WorkPriority.immediately; - - /// Copy with new priority - CryptoOperation copyWithPriority(WorkPriority newPriority) { - return CryptoOperation.withId( - id: id, - data: data, - cipherSequence: cipherSequence, - params: params, - type: type, - channelUuid: channelUuid, - messageSequence: messageSequence, - priority: newPriority, - ); - } - - @override - String toString() { - return 'CryptoOperation(' - 'id: $id, ' - 'type: $type, ' - 'dataSize: ${dataSize}B, ' - 'ciphers: ${cipherSequence.length}, ' - 'priority: $priority, ' - 'channel: $channelUuid' - ')'; - } - - @override - bool operator ==(Object other) => - identical(this, other) || - other is CryptoOperation && - runtimeType == other.runtimeType && - id == other.id; - - @override - int get hashCode => id.hashCode; -} diff --git a/flutter_src/ccc/ccc_iso_operation_id.dart b/flutter_src/ccc/ccc_iso_operation_id.dart deleted file mode 100644 index 6ecc619..0000000 --- a/flutter_src/ccc/ccc_iso_operation_id.dart +++ /dev/null @@ -1,96 +0,0 @@ -/// -/// -/// - -/// Fast sequence-based ID generator for crypto operations -/// Optimized for high-frequency crypto tasks with minimal overhead -class CryptoOperationId { - static int _counter = 0; - static late final String _sessionId; - static bool _initialized = false; - - /// Initialize the ID system with a new session - static void initialize() { - if (_initialized) return; // Don't reinitialize - _sessionId = DateTime.now().millisecondsSinceEpoch.toString(); - _counter = 0; - _initialized = true; - } - - /// Generate next operation ID - /// Format: "timestamp_sequence" - /// Example: "1692123456789_1" - static String generate() { - if (!_initialized) { - initialize(); - } - return '${_sessionId}_${++_counter}'; - } - - /// Get current session ID (for debugging) - static String get currentSession { - if (!_initialized) { - initialize(); - } - return _sessionId; - } - - /// Get total operations generated in this session - static int get operationCount => _counter; - - /// Reset counter (useful for testing) - static void reset() { - _counter = 0; - } - - /// Parse operation ID to extract session and sequence - static OperationIdInfo? parse(String operationId) { - final parts = operationId.split('_'); - if (parts.length != 2) return null; - - final sessionId = parts[0]; - final sequence = int.tryParse(parts[1]); - - if (sequence == null) return null; - - return OperationIdInfo( - sessionId: sessionId, - sequence: sequence, - operationId: operationId, - ); - } -} - -/// Information extracted from an operation ID -class OperationIdInfo { - final String sessionId; - final int sequence; - final String operationId; - - const OperationIdInfo({ - required this.sessionId, - required this.sequence, - required this.operationId, - }); - - /// Get session timestamp - DateTime? get sessionTimestamp { - final timestamp = int.tryParse(sessionId); - if (timestamp == null) return null; - return DateTime.fromMillisecondsSinceEpoch(timestamp); - } - - @override - String toString() => 'OperationIdInfo(session: $sessionId, sequence: $sequence)'; - - @override - bool operator ==(Object other) => - identical(this, other) || - other is OperationIdInfo && - runtimeType == other.runtimeType && - sessionId == other.sessionId && - sequence == other.sequence; - - @override - int get hashCode => sessionId.hashCode ^ sequence.hashCode; -} diff --git a/flutter_src/ccc/ccc_iso_result.dart b/flutter_src/ccc/ccc_iso_result.dart deleted file mode 100644 index 645c9d4..0000000 --- a/flutter_src/ccc/ccc_iso_result.dart +++ /dev/null @@ -1,220 +0,0 @@ -/// -/// Result structure for crypto operations -/// Handles success/error states and performance metrics -/// - -/// Result of a cryptographic operation -class CryptoResult { - final String operationId; - final List data; - final bool success; - final String? error; - final String? stackTrace; - final Duration processingTime; - final String workerId; - final DateTime completedAt; - - /// Create successful result - CryptoResult.success({ - required this.operationId, - required this.data, - required this.processingTime, - required this.workerId, - }) : success = true, - error = null, - stackTrace = null, - completedAt = DateTime.now(); - - /// Create error result - CryptoResult.error({ - required this.operationId, - required this.error, - this.stackTrace, - required this.processingTime, - required this.workerId, - }) : success = false, - data = const [], - completedAt = DateTime.now(); - - /// Serialize for isolate communication - Map toMap() { - return { - 'operationId': operationId, - 'data': data, - 'success': success, - 'error': error, - 'stackTrace': stackTrace, - 'processingTimeMs': processingTime.inMilliseconds, - 'workerId': workerId, - 'completedAtMs': completedAt.millisecondsSinceEpoch, - }; - } - - /// Deserialize from isolate communication - static CryptoResult fromMap(Map map) { - final success = map['success'] as bool; - final processingTime = Duration(milliseconds: map['processingTimeMs'] as int); - final workerId = map['workerId'] as String; - final operationId = map['operationId'] as String; - - if (success) { - return CryptoResult.success( - operationId: operationId, - data: List.from(map['data'] as List), - processingTime: processingTime, - workerId: workerId, - ); - } else { - return CryptoResult.error( - operationId: operationId, - error: map['error'] as String?, - stackTrace: map['stackTrace'] as String?, - processingTime: processingTime, - workerId: workerId, - ); - } - } - - /// Get result data size in bytes - int get dataSize => data.length; - - /// Get processing speed in bytes per second - double get bytesPerSecond { - final seconds = processingTime.inMilliseconds / 1000.0; - if (seconds <= 0) return 0.0; - return dataSize / seconds; - } - - /// Get human-readable processing speed - String get formattedSpeed { - final bps = bytesPerSecond; - if (bps >= 1024 * 1024) { - return '${(bps / (1024 * 1024)).toStringAsFixed(2)} MB/s'; - } else if (bps >= 1024) { - return '${(bps / 1024).toStringAsFixed(2)} KB/s'; - } else { - return '${bps.toStringAsFixed(2)} B/s'; - } - } - - /// Check if operation was slow - bool get isSlow => processingTime.inMilliseconds > 1000; // > 1 second - - /// Check if operation was fast - bool get isFast => processingTime.inMilliseconds < 100; // < 100ms - - @override - String toString() { - if (success) { - return 'CryptoResult.success(' - 'id: $operationId, ' - 'dataSize: ${dataSize}B, ' - 'time: ${processingTime.inMilliseconds}ms, ' - 'speed: $formattedSpeed, ' - 'worker: $workerId' - ')'; - } else { - return 'CryptoResult.error(' - 'id: $operationId, ' - 'error: $error, ' - 'time: ${processingTime.inMilliseconds}ms, ' - 'worker: $workerId' - ')'; - } - } - - @override - bool operator ==(Object other) => - identical(this, other) || - other is CryptoResult && - runtimeType == other.runtimeType && - operationId == other.operationId && - success == other.success; - - @override - int get hashCode => operationId.hashCode ^ success.hashCode; -} - -/// Performance metrics for crypto operations -class CryptoMetrics { - int encryptionCount = 0; - int decryptionCount = 0; - Duration totalEncryptionTime = Duration.zero; - Duration totalDecryptionTime = Duration.zero; - int errorCount = 0; - int priorityOperations = 0; - DateTime? lastOperationTime; - - /// Record successful encryption - void recordEncryption(Duration time, bool wasPriority) { - encryptionCount++; - totalEncryptionTime += time; - if (wasPriority) priorityOperations++; - lastOperationTime = DateTime.now(); - } - - /// Record successful decryption - void recordDecryption(Duration time) { - decryptionCount++; - totalDecryptionTime += time; - lastOperationTime = DateTime.now(); - } - - /// Record error - void recordError() { - errorCount++; - lastOperationTime = DateTime.now(); - } - - /// Get total operations - int get totalOperations => encryptionCount + decryptionCount; - - /// Get average encryption time - Duration get averageEncryptionTime { - if (encryptionCount == 0) return Duration.zero; - return Duration(milliseconds: totalEncryptionTime.inMilliseconds ~/ encryptionCount); - } - - /// Get average decryption time - Duration get averageDecryptionTime { - if (decryptionCount == 0) return Duration.zero; - return Duration(milliseconds: totalDecryptionTime.inMilliseconds ~/ decryptionCount); - } - - /// Get error rate (0.0 to 1.0) - double get errorRate { - final total = totalOperations + errorCount; - if (total == 0) return 0.0; - return errorCount / total; - } - - /// Get priority operation percentage - double get priorityPercentage { - if (totalOperations == 0) return 0.0; - return priorityOperations / totalOperations; - } - - /// Reset all metrics - void reset() { - encryptionCount = 0; - decryptionCount = 0; - totalEncryptionTime = Duration.zero; - totalDecryptionTime = Duration.zero; - errorCount = 0; - priorityOperations = 0; - lastOperationTime = null; - } - - @override - String toString() { - return 'CryptoMetrics(' - 'operations: $totalOperations, ' - 'encryptions: $encryptionCount, ' - 'decryptions: $decryptionCount, ' - 'errors: $errorCount, ' - 'avgEncTime: ${averageEncryptionTime.inMilliseconds}ms, ' - 'avgDecTime: ${averageDecryptionTime.inMilliseconds}ms, ' - 'errorRate: ${(errorRate * 100).toStringAsFixed(1)}%' - ')'; - } -} diff --git a/flutter_src/ccc/ccc_kdf.dart b/flutter_src/ccc/ccc_kdf.dart deleted file mode 100644 index eaa5b27..0000000 --- a/flutter_src/ccc/ccc_kdf.dart +++ /dev/null @@ -1,40 +0,0 @@ -/// CCC Key-Derivation Function (KDF) definitions and helpers. -/// -/// This module owns: -/// - stable int-backed KDF identifiers for persistence, -/// - normalization/parsing helpers, -/// - conversion from persisted int to enum. -/// -/// Keeping this in `ccc/` preserves separation of concerns so data models remain -/// focused on storage shape only. -enum CccKdfFunction { - sha256(1), - sha384(2), - sha512(3), - blake2b512(4); - - final int value; - const CccKdfFunction(this.value); -} - -/// Default persisted KDF selector. -const int cccDefaultKdfFunctionValue = 1; - -/// Normalize arbitrary input to a supported KDF function int value. -int normalizeCccKdfFunctionValue(dynamic raw) { - final parsed = raw is int ? raw : int.tryParse(raw?.toString() ?? ''); - if (parsed == null) return cccDefaultKdfFunctionValue; - - for (final option in CccKdfFunction.values) { - if (option.value == parsed) return parsed; - } - return cccDefaultKdfFunctionValue; -} - -/// Resolve an enum value from persisted int representation. -CccKdfFunction cccKdfFunctionFromInt(int raw) { - for (final option in CccKdfFunction.values) { - if (option.value == raw) return option; - } - return CccKdfFunction.sha256; -} diff --git a/flutter_src/ccc/ccc_key_schedule.dart b/flutter_src/ccc/ccc_key_schedule.dart deleted file mode 100644 index f00ffaa..0000000 --- a/flutter_src/ccc/ccc_key_schedule.dart +++ /dev/null @@ -1,148 +0,0 @@ -import 'dart:convert'; - -import 'package:cryptography/cryptography.dart'; -/// local imports -import 'package:letusmsg/ccc/ccc_kdf.dart'; -import 'package:letusmsg/data/ccc_data.dart'; - -/// Phase 1 key schedule helper. -/// -/// This utility derives deterministic channel-root and per-message key material -/// with a selectable KDF/hash option so message/attachment flows can share one -/// key-schedule contract before full ratchet rollout. -class CccKeySchedule { - static const String version = 'phase1-v1'; - - /// Derive the deterministic 32-byte root key for a channel. - /// - /// This is the shared secret that all channel members can independently - /// compute from the channel UUID and CCCData configuration. Used both - /// by the Phase 1 static key schedule and as the seed for Phase 2 - /// ratchet initialization via [RatchetEngine.initializeFromRoot]. - /// - /// Returns a 32-byte root key (truncated from the full hash output). - static Future> deriveRootKey({ - required String channelUuid, - required CCCData? cccData, - }) async { - final combo = cccData?.combo ?? 0; - final iterations = cccData?.iterrations ?? 0; - final kdfFunctionValue = normalizeCccKdfFunctionValue( - cccData?.kdfFunction, - ); - final kdfFunction = cccKdfFunctionFromInt(kdfFunctionValue); - final fullHash = await _hashUtf8( - 'lum|$version|root|$channelUuid|combo:$combo|iter:$iterations', - kdfFunction, - ); - return fullHash.sublist(0, 32); - } - - /// Build Phase 1 key-schedule params for one channel/message operation. - /// - /// The returned params are additive and safe to merge with existing CCC params. - static Future buildMessageParams({ - required String channelUuid, - required CCCData? cccData, - required Map baseCipherParams, - required bool isUserMessage, - int? messageSequence, - }) async { - final combo = cccData?.combo ?? 0; - final iterations = cccData?.iterrations ?? 0; - final kdfFunctionValue = normalizeCccKdfFunctionValue( - cccData?.kdfFunction, - ); - final kdfFunction = cccKdfFunctionFromInt(kdfFunctionValue); - final effectiveSequence = messageSequence ?? 0; - - final rootKey = await _hashUtf8( - 'lum|$version|root|$channelUuid|combo:$combo|iter:$iterations', - kdfFunction, - ); - - final direction = isUserMessage ? 'out' : 'in'; - final messageKey = await _hashBytes( - [ - ...rootKey, - ...utf8.encode('|msg|$direction|seq:$effectiveSequence'), - ], - kdfFunction, - ); - - // Note: direction and message_sequence are included in the AD map for - // key-schedule metadata completeness, but are stripped by the isolate - // worker's _buildAssociatedDataBytes() before AEAD binding. This is - // intentional for Phase 1: the sender does not know the relay-assigned - // server_seq at encryption time, and direction differs between sender - // ('out') and receiver ('in'). Phase 2 ratchet will re-enable sequence - // binding once both sides share agreed-upon counters. - final associatedData = { - 'v': version, - 'channel_uuid': channelUuid, - 'ccc_combo': combo, - 'ccc_iterations': iterations, - 'message_sequence': effectiveSequence, - 'direction': direction, - 'kdf_function': kdfFunction.name, - 'kdf_function_value': kdfFunction.value, - }; - - return CccPhase1KeyMaterial( - effectiveMessageSequence: effectiveSequence, - cipherParams: { - ...baseCipherParams, - 'phase1_key_schedule_version': version, - 'phase1_kdf_function': kdfFunction.name, - 'phase1_kdf_function_value': kdfFunction.value, - 'phase1_effective_sequence': effectiveSequence, - 'phase1_root_key_b64': _toBase64UrlNoPad(rootKey), - 'phase1_message_key_b64': _toBase64UrlNoPad(messageKey), - 'phase1_associated_data': associatedData, - }, - ); - } - - /// Hash UTF-8 text to bytes using selected KDF/hash function. - static Future> _hashUtf8( - String value, - CccKdfFunction kdfFunction, - ) async { - return _hashBytes(utf8.encode(value), kdfFunction); - } - - /// Hash bytes to bytes using selected KDF/hash function. - static Future> _hashBytes( - List bytes, - CccKdfFunction kdfFunction, - ) async { - switch (kdfFunction) { - case CccKdfFunction.sha256: - return (await Sha256().hash(bytes)).bytes; - case CccKdfFunction.sha384: - return (await Sha384().hash(bytes)).bytes; - case CccKdfFunction.sha512: - return (await Sha512().hash(bytes)).bytes; - case CccKdfFunction.blake2b512: - return (await Blake2b().hash(bytes)).bytes; - } - } - - static String _toBase64UrlNoPad(List bytes) { - return base64UrlEncode(bytes).replaceAll('=', ''); - } -} - -/// Derived key material metadata for Phase 1 message encryption scheduling. -class CccPhase1KeyMaterial { - /// Effective message sequence used for this derivation. - final int effectiveMessageSequence; - - /// Parameters merged into CCC cipher params for runtime usage. - final Map cipherParams; - - const CccPhase1KeyMaterial({ - required this.effectiveMessageSequence, - required this.cipherParams, - }); -} diff --git a/flutter_src/ccc/ccc_provider_spec.dart b/flutter_src/ccc/ccc_provider_spec.dart deleted file mode 100644 index 6578720..0000000 --- a/flutter_src/ccc/ccc_provider_spec.dart +++ /dev/null @@ -1,182 +0,0 @@ -/// -/// CCC provider specification models. -/// - -import 'package:letusmsg/ccc/cipher_constants.dart'; - -/// Execution strategy for provider routing inside CCC. -enum CccExecutionMode { - strict, - efficient, - auto, -} - -CccExecutionMode cccExecutionModeFromString(String raw) { - switch (raw.trim().toLowerCase()) { - case 'strict': - return CccExecutionMode.strict; - case 'efficient': - return CccExecutionMode.efficient; - case 'auto': - return CccExecutionMode.auto; - default: - throw ArgumentError('Unsupported CCC execution mode: $raw'); - } -} - -/// Logical provider identities used by CCC channel profiles. -enum CccCryptoProvider { - cryptography, - wolfssl, - openssl, - boringssl, -} - -/// Provider entry in a CCC provider chain. -/// -/// Each provider advertises the ciphers it contributes to the channel plan. -class CccProviderSpec { - final CccCryptoProvider provider; - final List ciphers; - - const CccProviderSpec({ - required this.provider, - required this.ciphers, - }); - - Map toMap() { - return { - 'provider': provider.name, - 'ciphers': ciphers, - }; - } -} - -/// Per-provider, per-cipher capability metadata. -class CccCipherCapability { - /// Whether the provider is currently available in this codebase/runtime. - /// - /// `true` means the provider can be selected as primary in `auto` mode. - /// `false` means it can still appear in route planning metadata but should - /// not be chosen as active primary until availability changes. - final bool available; - - /// Whether input/output format is identical across providers for this cipher. - /// - /// This guards fallback safety. If this is `false`, fallback should be - /// treated as incompatible for that cipher unless a migration adapter exists. - final bool deterministicIo; - - /// Relative efficiency score from 0..100 (higher = faster/cheaper). - /// - /// Used by `efficient` mode to rank candidate providers for a cipher. - final int efficiencyScore; - - /// Relative reliability score from 0..100 (higher = more trusted/stable). - /// - /// Used as tie-breaker when efficiency scores are equal. - final int reliabilityScore; - - /// Creates immutable provider capability metadata used by CCC route planning. - /// - /// Parameter meanings: - /// - [available]: runtime/provider readiness flag. - /// - [deterministicIo]: indicates safe cross-provider fallback compatibility. - /// - [efficiencyScore]: performance rank (0..100), higher is better. - /// - [reliabilityScore]: confidence rank (0..100), higher is better. - const CccCipherCapability({ - required this.available, - required this.deterministicIo, - required this.efficiencyScore, - required this.reliabilityScore, - }); -} - -/// Runtime/provider capability registry used by CCC route planning. -class CccProviderCatalog { - /// Placeholder score used until benchmark pipeline is implemented. - /// - /// TODO(j3g): Replace with measured values from automated perf/reliability - /// benchmark suite per provider/cipher. - /// - /// Example efficiency calculation (normalized 0..100): - /// efficiency = normalize(throughputMBps / latencyMs) - /// - /// Example reliability calculation (normalized 0..100): - /// reliability = normalize((1 - errorRate) * 100 - crashPenalty - cvePenalty) - static const int pendingEfficiencyScore = 50; - static const int pendingReliabilityScore = 50; - - static const CccCipherCapability _availableDeterministicPending = CccCipherCapability( - available: true, - deterministicIo: true, - efficiencyScore: pendingEfficiencyScore, - reliabilityScore: pendingReliabilityScore, - ); - - static const CccCipherCapability _unavailableDeterministicPending = CccCipherCapability( - available: false, - deterministicIo: true, - efficiencyScore: pendingEfficiencyScore, - reliabilityScore: pendingReliabilityScore, - ); - - static const Map> capabilities = { - CccCryptoProvider.cryptography: { - CipherConstants.AES_GCM_256: _availableDeterministicPending, - CipherConstants.CHACHA20_POLY1305: _availableDeterministicPending, - CipherConstants.XCHACHA20_POLY1305: _availableDeterministicPending, - CipherConstants.HMAC_SHA512: _availableDeterministicPending, - CipherConstants.BLAKE2B: _availableDeterministicPending, - }, - CccCryptoProvider.wolfssl: { - CipherConstants.AES_GCM_256: _unavailableDeterministicPending, - CipherConstants.CHACHA20_POLY1305: _unavailableDeterministicPending, - CipherConstants.XCHACHA20_POLY1305: _unavailableDeterministicPending, - CipherConstants.HMAC_SHA512: _unavailableDeterministicPending, - CipherConstants.BLAKE2B: _unavailableDeterministicPending, - }, - CccCryptoProvider.openssl: { - CipherConstants.AES_GCM_256: _unavailableDeterministicPending, - CipherConstants.CHACHA20_POLY1305: _unavailableDeterministicPending, - CipherConstants.HMAC_SHA512: _unavailableDeterministicPending, - CipherConstants.BLAKE2B: _unavailableDeterministicPending, - }, - CccCryptoProvider.boringssl: { - CipherConstants.AES_GCM_256: _unavailableDeterministicPending, - CipherConstants.CHACHA20_POLY1305: _unavailableDeterministicPending, - CipherConstants.XCHACHA20_POLY1305: _unavailableDeterministicPending, - CipherConstants.HMAC_SHA512: _unavailableDeterministicPending, - CipherConstants.BLAKE2B: _unavailableDeterministicPending, - }, - }; - - static CccCipherCapability? capability(CccCryptoProvider provider, int cipher) { - return capabilities[provider]?[cipher]; - } - - static bool supports(CccCryptoProvider provider, int cipher) { - return capability(provider, cipher) != null; - } - - static List providersSupporting( - int cipher, { - bool availableOnly = true, - }) { - final ranked = <({CccCryptoProvider provider, CccCipherCapability capability})>[]; - for (final entry in capabilities.entries) { - final cap = entry.value[cipher]; - if (cap == null) continue; - if (availableOnly && !cap.available) continue; - ranked.add((provider: entry.key, capability: cap)); - } - - ranked.sort((a, b) { - final perf = b.capability.efficiencyScore.compareTo(a.capability.efficiencyScore); - if (perf != 0) return perf; - return b.capability.reliabilityScore.compareTo(a.capability.reliabilityScore); - }); - - return ranked.map((item) => item.provider).toList(growable: false); - } -} diff --git a/flutter_src/ccc/cipher_constants.dart b/flutter_src/ccc/cipher_constants.dart deleted file mode 100644 index 162934f..0000000 --- a/flutter_src/ccc/cipher_constants.dart +++ /dev/null @@ -1,209 +0,0 @@ -/// -/// Cipher Constants for Copious Cipher Chain -/// Integer constants for efficient cipher sequence storage and processing -/// - -class CipherConstants { - // Key Derivation Functions - static const int ARGON2ID = 1; - static const int PBKDF2 = 2; - static const int HKDF = 3; - static const int HCHACHA20 = 4; - - // Symmetric Ciphers (AEAD) - static const int AES_GCM_128 = 10; - static const int AES_GCM_192 = 11; - static const int AES_GCM_256 = 12; - static const int CHACHA20_POLY1305 = 13; - static const int XCHACHA20_POLY1305 = 14; - - // Symmetric Ciphers (Non-AEAD) - static const int AES_CBC_128 = 20; - static const int AES_CBC_192 = 21; - static const int AES_CBC_256 = 22; - static const int AES_CTR_128 = 23; - static const int AES_CTR_192 = 24; - static const int AES_CTR_256 = 25; - static const int CHACHA20 = 26; - static const int XCHACHA20 = 27; - - // MAC Algorithms - static const int HMAC_SHA256 = 30; - static const int HMAC_SHA384 = 31; - static const int HMAC_SHA512 = 32; - static const int BLAKE2B = 33; - static const int BLAKE2S = 34; - static const int POLY1305 = 35; - - // Hash Algorithms (for integrity verification) - static const int SHA256 = 40; - static const int SHA384 = 41; - static const int SHA512 = 42; - static const int BLAKE2B_HASH = 43; - static const int BLAKE2S_HASH = 44; - - // Phase 1 Default Cipher Sequence (5 layers - Argon2id removed for proper reversibility) - static const List PHASE1_SEQUENCE = [ - AES_GCM_256, // Primary AEAD encryption - CHACHA20_POLY1305, // Stream cipher AEAD - XCHACHA20_POLY1305, // Extended nonce AEAD - HMAC_SHA512, // Additional authentication - BLAKE2B, // Final integrity check - ]; - - // Complete sequence with key derivation (for future use) - static const List PHASE1_COMPLETE_SEQUENCE = [ - ARGON2ID, // Key strengthening (one-way - use for key derivation only) - AES_GCM_256, // Primary AEAD encryption - CHACHA20_POLY1305, // Stream cipher AEAD - XCHACHA20_POLY1305, // Extended nonce AEAD - HMAC_SHA512, // Additional authentication - BLAKE2B, // Final integrity check - ]; - - // --- Basic / user-selectable cipher sequences (combo 5-9) ---------------- - - /// Single-layer AES-256-GCM (combo 5). - static const List BASIC_AES_SEQUENCE = [AES_GCM_256]; - - /// Single-layer ChaCha20-Poly1305 (combo 6). - static const List BASIC_CHACHA_SEQUENCE = [CHACHA20_POLY1305]; - - /// Single-layer XChaCha20-Poly1305 (combo 7). - static const List BASIC_XCHACHA_SEQUENCE = [XCHACHA20_POLY1305]; - - /// Dual AEAD: AES-256-GCM + ChaCha20-Poly1305 (combo 8). - static const List DUAL_AEAD_SEQUENCE = [AES_GCM_256, CHACHA20_POLY1305]; - - /// Triple AEAD: AES + ChaCha20 + XChaCha20 (combo 9). - static const List TRIPLE_AEAD_SEQUENCE = [AES_GCM_256, CHACHA20_POLY1305, XCHACHA20_POLY1305]; - - // Default cipher parameters - static const Map DEFAULT_CIPHER_PARAMS = { - // Argon2id parameters - 'argon2_memory': 64 * 1024, // 64 MB - 'argon2_parallelism': 4, // 4 CPU cores - 'argon2_iterations': 3, // 3 iterations - 'argon2_hash_length': 32, // 256-bit output - - // AES parameters - 'aes_key_size': 256, // 256-bit keys - 'aes_nonce_size': 12, // 96-bit nonces for GCM - - // ChaCha parameters - 'chacha_nonce_size': 12, // 96-bit nonces - 'xchacha_nonce_size': 24, // 192-bit nonces - - // HMAC parameters - 'hmac_key_size': 64, // 512-bit keys - - // BLAKE2B parameters - 'blake2b_hash_size': 64, // 512-bit hashes - }; - - // Cipher name mapping for debugging - static const Map CIPHER_NAMES = { - // Key Derivation - ARGON2ID: 'Argon2id', - PBKDF2: 'PBKDF2', - HKDF: 'HKDF', - HCHACHA20: 'HChaCha20', - - // AEAD Ciphers - AES_GCM_128: 'AES-128-GCM', - AES_GCM_192: 'AES-192-GCM', - AES_GCM_256: 'AES-256-GCM', - CHACHA20_POLY1305: 'ChaCha20-Poly1305', - XCHACHA20_POLY1305: 'XChaCha20-Poly1305', - - // Non-AEAD Ciphers - AES_CBC_128: 'AES-128-CBC', - AES_CBC_192: 'AES-192-CBC', - AES_CBC_256: 'AES-256-CBC', - AES_CTR_128: 'AES-128-CTR', - AES_CTR_192: 'AES-192-CTR', - AES_CTR_256: 'AES-256-CTR', - CHACHA20: 'ChaCha20', - XCHACHA20: 'XChaCha20', - - // MAC Algorithms - HMAC_SHA256: 'HMAC-SHA256', - HMAC_SHA384: 'HMAC-SHA384', - HMAC_SHA512: 'HMAC-SHA512', - BLAKE2B: 'BLAKE2b', - BLAKE2S: 'BLAKE2s', - POLY1305: 'Poly1305', - - // Hash Algorithms - SHA256: 'SHA256', - SHA384: 'SHA384', - SHA512: 'SHA512', - BLAKE2B_HASH: 'BLAKE2b-Hash', - BLAKE2S_HASH: 'BLAKE2s-Hash', - }; - - /// Get human-readable name for cipher constant - static String getCipherName(int cipherConstant) { - return CIPHER_NAMES[cipherConstant] ?? 'Unknown Cipher ($cipherConstant)'; - } - - /// Get human-readable sequence description - static String getSequenceDescription(List sequence) { - return sequence.map((cipher) => getCipherName(cipher)).join(' -> '); - } - - /// Validate cipher sequence - static bool isValidSequence(List sequence) { - // Empty sequence is valid – it represents the plaintext/legacy combo 0. - if (sequence.isEmpty) return true; - - // Check all ciphers are known - for (final cipher in sequence) { - if (!CIPHER_NAMES.containsKey(cipher)) { - return false; - } - } - - return true; - } - - // --- Combo metadata ------------------------------------------------------- - - /// Human-readable names for each combo value. - /// - /// Combos 0-4 are multi-layer / multi-provider configurations. - /// Combos 5-9 are user-selectable "basic" through "triple AEAD" options. - static const Map COMBO_NAMES = { - 0: 'Plaintext (legacy / unencrypted)', - 1: 'Multi-Provider: wolfSSL + CCC', - 2: 'Multi-Provider: BoringSSL + CCC', - 3: 'Multi-Provider: OpenSSL + wolfSSL + CCC', - 4: 'Multi-Provider: wolfSSL + OpenSSL + CCC', - 5: 'Basic: AES-256-GCM', - 6: 'Basic: ChaCha20-Poly1305', - 7: 'Basic: XChaCha20-Poly1305', - 8: 'Dual AEAD: AES + ChaCha20', - 9: 'Triple AEAD: AES + ChaCha20 + XChaCha20', - }; - - /// Cipher sequence for each combo value. - static const Map> COMBO_SEQUENCES = { - 0: [], // plaintext / legacy – empty sequence = no cipher layers - 5: BASIC_AES_SEQUENCE, - 6: BASIC_CHACHA_SEQUENCE, - 7: BASIC_XCHACHA_SEQUENCE, - 8: DUAL_AEAD_SEQUENCE, - 9: TRIPLE_AEAD_SEQUENCE, - }; - - /// Maximum supported combo value. - static const int MAX_COMBO = 9; - - /// Whether [combo] is a valid, known combo value. - static bool isValidCombo(int combo) => COMBO_NAMES.containsKey(combo); - - /// Get the human-readable name for a combo, or a fallback string. - static String getComboName(int combo) { - return COMBO_NAMES[combo] ?? 'Unknown Combo ($combo)'; - } -} diff --git a/flutter_src/ccc/copious_cipher_chain.dart b/flutter_src/ccc/copious_cipher_chain.dart deleted file mode 100644 index 8895414..0000000 --- a/flutter_src/ccc/copious_cipher_chain.dart +++ /dev/null @@ -1,116 +0,0 @@ -/// -/// -/// -import 'ccc_iso_manager.dart'; -import 'ccc_iso_result.dart'; -import 'cipher_constants.dart'; - -/// Copious Cipher Chain - Phase 1 with Isolate Support -/// Now supports async operations using CryptoIsolateManager -class CopiousCipherChain { - final CryptoIsolateManager? _isolateManager; // New isolate-based crypto - final List _cipherSequence; // Integer-based cipher sequence - final Map _cipherParams; // Cipher parameters - - /// New constructor with isolate manager (Phase 1) - CopiousCipherChain.withIsolateManager({ - required CryptoIsolateManager isolateManager, - List? cipherSequence, - Map? cipherParams, - }) : _isolateManager = isolateManager, - _cipherSequence = cipherSequence ?? CipherConstants.PHASE1_SEQUENCE, - _cipherParams = cipherParams ?? CipherConstants.DEFAULT_CIPHER_PARAMS; - - /// Async encrypt with isolate support - Future> encryptAsync( - List data, { - required String channelUuid, - int? messageSequence, - bool isUserMessage = false, - List? customCipherSequence, - Map? customParams, - }) async { - if (_isolateManager == null) { - throw StateError('Isolate manager not available. Use legacy encrypt() or create with withIsolateManager()'); - } - - final result = await _isolateManager.encrypt( - data, - channelUuid: channelUuid, - messageSequence: messageSequence, - cipherSequence: customCipherSequence ?? _cipherSequence, - params: customParams ?? _cipherParams, - isUserMessage: isUserMessage, - ); - - if (!result.success) { - throw Exception('Encryption failed: ${result.error}'); - } - - return result.data; - } - - /// Async decrypt with isolate support - Future> decryptAsync( - List data, { - required String channelUuid, - int? messageSequence, - List? customCipherSequence, - Map? customParams, - }) async { - if (_isolateManager == null) { - throw StateError('Isolate manager not available. Use legacy decrypt() or create with withIsolateManager()'); - } - - final result = await _isolateManager.decrypt( - data, - channelUuid: channelUuid, - messageSequence: messageSequence, - cipherSequence: customCipherSequence ?? _cipherSequence, - params: customParams ?? _cipherParams, - ); - - if (!result.success) { - throw Exception('Decryption failed: ${result.error}'); - } - - return result.data; - } - - /// Test the cipher chain with a roundtrip operation - Future testCipherChain({ - String testData = 'Test message for cipher chain validation', - String channelUuid = 'test-channel-999', - }) async { - if (_isolateManager == null) { - return false; // Cannot test without isolate manager - } - - try { - final result = await _isolateManager.testOperation( - testData: testData, - channelUuid: channelUuid, - ); - return result.success; - } catch (e) { - return false; - } - } - - /// Get cipher sequence description - String get cipherSequenceDescription { - return CipherConstants.getSequenceDescription(_cipherSequence); - } - - /// Get performance metrics (if using isolate manager) - CryptoMetrics? get metrics => _isolateManager?.metrics; - - /// Check if using isolate manager - bool get usesIsolateManager => _isolateManager != null; - - /// Get current cipher sequence - List get cipherSequence => List.from(_cipherSequence); - - /// Get current cipher parameters - Map get cipherParams => Map.from(_cipherParams); -} diff --git a/flutter_src/ccc/crypto_abstract.dart b/flutter_src/ccc/crypto_abstract.dart deleted file mode 100644 index ed6a8c3..0000000 --- a/flutter_src/ccc/crypto_abstract.dart +++ /dev/null @@ -1,69 +0,0 @@ -/// -/// Core crypto contract used by message/attachment pipelines. -/// - -/// Generic encryption/decryption contract. -/// -/// Implementations include: -/// - plaintext/testing providers, -/// - CCC isolate-backed providers, -/// - native FFI-backed providers. -abstract class CryptoAbstract { - /// Human readable provider name for logs/diagnostics. - String get providerName; - - /// True when provider does not apply real cryptographic protection. - bool get isPlaintextMode; - - /// Encrypt typed input into bytes. - Future> encrypt(T input, {CryptoContext? context}); - - /// Decrypt bytes back to typed data. - Future decrypt(List data, {CryptoContext? context}); -} - -/// Per-operation context for crypto providers. -/// -/// Providers that require channel-scoped or message-scoped key derivation -/// can consume these values. Plaintext/testing providers can ignore them. -class CryptoContext { - /// Stable channel UUID used for channel-scoped keying. - final String? channelUuid; - - /// Optional message sequence used for per-message key derivation. - final int? messageSequence; - - /// Priority hint for provider internals. - final bool isUserMessage; - - /// Optional channel-derived cipher sequence override. - final List? cipherSequence; - - /// Optional channel-derived cipher params override. - final Map? cipherParams; - - const CryptoContext({ - this.channelUuid, - this.messageSequence, - this.isUserMessage = false, - this.cipherSequence, - this.cipherParams, - }); -} - -CryptoProviderMode cryptoProviderModeFromString(String raw) { - final value = raw.trim().toLowerCase(); - switch (value) { - case 'plaintext': - return CryptoProviderMode.plaintext; - case 'ccc': - return CryptoProviderMode.ccc; - default: - throw ArgumentError('Unsupported crypto provider mode: $raw'); - } -} - -enum CryptoProviderMode { - plaintext, - ccc, -} diff --git a/flutter_src/ccc/crypto_ccc.dart b/flutter_src/ccc/crypto_ccc.dart deleted file mode 100644 index c1e4f3b..0000000 --- a/flutter_src/ccc/crypto_ccc.dart +++ /dev/null @@ -1,81 +0,0 @@ -/// -/// CCC isolate-backed crypto provider for message payloads. -/// -import 'dart:convert'; - -import 'package:letusmsg/ccc/ccc_iso_manager.dart'; -import 'package:letusmsg/ccc/crypto_abstract.dart'; - -/// Real crypto provider backed by `CryptoIsolateManager`. -/// -/// Notes: -/// - Requires `context.channelUuid` for channel-scoped operation. -/// - Uses JSON map serialization for current message payload format. -class CryptoCcc implements CryptoAbstract> { - final CryptoIsolateManager _manager; - bool _initialized = false; - - CryptoCcc(this._manager); - - @override - String get providerName => 'CryptoCcc'; - - @override - bool get isPlaintextMode => false; - - Future _ensureInitialized() async { - if (_initialized) return; - await _manager.initialize(); - _initialized = true; - } - - String _requireChannelUuid(CryptoContext? context) { - final channelUuid = context?.channelUuid; - if (channelUuid == null || channelUuid.isEmpty) { - throw ArgumentError('CryptoCcc requires a non-empty channelUuid in CryptoContext'); - } - return channelUuid; - } - - @override - Future> encrypt(Map input, {CryptoContext? context}) async { - await _ensureInitialized(); - final channelUuid = _requireChannelUuid(context); - - final plainBytes = utf8.encode(jsonEncode(input)); - final result = await _manager.encrypt( - plainBytes, - channelUuid: channelUuid, - messageSequence: context?.messageSequence, - cipherSequence: context?.cipherSequence, - params: context?.cipherParams, - isUserMessage: context?.isUserMessage ?? false, - ); - - if (!result.success) { - throw Exception('CryptoCcc encrypt failed: ${result.error ?? 'unknown error'}'); - } - - return result.data; - } - - @override - Future> decrypt(List data, {CryptoContext? context}) async { - await _ensureInitialized(); - final channelUuid = _requireChannelUuid(context); - - final result = await _manager.decrypt( - data, - channelUuid: channelUuid, - messageSequence: context?.messageSequence, - cipherSequence: context?.cipherSequence, - params: context?.cipherParams, - ); - - if (!result.success) { - throw Exception('CryptoCcc decrypt failed: ${result.error ?? 'unknown error'}'); - } - - return jsonDecode(utf8.decode(result.data)); - } -} diff --git a/flutter_src/ccc/crypto_plaintext.dart b/flutter_src/ccc/crypto_plaintext.dart deleted file mode 100644 index 7297489..0000000 --- a/flutter_src/ccc/crypto_plaintext.dart +++ /dev/null @@ -1,13 +0,0 @@ -/// -/// Preferred plaintext provider naming. -/// -import 'package:letusmsg/ccc/enc_dec_json.dart'; - -/// Plaintext/testing provider alias. -/// -/// Keeps compatibility with existing EncDecJson behavior while making -/// provider intent explicit in pipeline wiring. -class CryptoPlaintext extends EncDecJson { - @override - String get providerName => 'CryptoPlaintext'; -} diff --git a/flutter_src/ccc/crypto_wolfssl.dart b/flutter_src/ccc/crypto_wolfssl.dart deleted file mode 100644 index 41908fc..0000000 --- a/flutter_src/ccc/crypto_wolfssl.dart +++ /dev/null @@ -1,26 +0,0 @@ -/// -/// Native wolfSSL provider scaffold. -/// -import 'package:letusmsg/ccc/crypto_abstract.dart'; - -/// Phase-0 scaffold for future wolfSSL FFI integration. -/// -/// This provider is intentionally not implemented yet. It exists so pipeline -/// wiring and provider selection can be completed before FFI delivery. -class CryptoWolfSsl implements CryptoAbstract> { - @override - String get providerName => 'CryptoWolfSsl'; - - @override - bool get isPlaintextMode => false; - - @override - Future> encrypt(Map input, {CryptoContext? context}) { - throw UnimplementedError('CryptoWolfSsl.encrypt is not implemented yet (Phase 3)'); - } - - @override - Future> decrypt(List data, {CryptoContext? context}) { - throw UnimplementedError('CryptoWolfSsl.decrypt is not implemented yet (Phase 3)'); - } -} diff --git a/flutter_src/ccc/enc_dec_json.dart b/flutter_src/ccc/enc_dec_json.dart deleted file mode 100644 index 7f3503a..0000000 --- a/flutter_src/ccc/enc_dec_json.dart +++ /dev/null @@ -1,43 +0,0 @@ -/// -/// Enc/Dec JSON implementation -/// -import 'dart:convert'; -import 'package:letusmsg/ccc/crypto_abstract.dart'; - - -/// Plaintext JSON codec used for testing/development flows. -/// -/// This class intentionally does not provide cryptographic protection. -class EncDecJson implements CryptoAbstract> { - - @override - String get providerName => 'EncDecJson'; - - @override - bool get isPlaintextMode => true; - - // @override - // List pre(String input) { - // return utf8.encode(input); - // } - - @override - Future> encrypt(Map data, {CryptoContext? context}) async { - // Simulate encryption delay - // await Future.delayed(Duration(milliseconds: 100)); - return utf8.encode( jsonEncode(data) ); - } - - @override - Future> decrypt(List encdata, {CryptoContext? context}) async { - // Simulate decryption delay - // await Future.delayed(Duration(milliseconds: 100)); - return jsonDecode(utf8.decode(encdata)); - } - - // @override - // String post(List output) { - // return utf8.decode(output); - // } - -} diff --git a/flutter_src/ccc/ratchet_engine.dart b/flutter_src/ccc/ratchet_engine.dart deleted file mode 100644 index 0c88fc3..0000000 --- a/flutter_src/ccc/ratchet_engine.dart +++ /dev/null @@ -1,497 +0,0 @@ -/// -/// Ratchet Engine – Double Ratchet Core for Normal Mode -/// -/// Pure-logic class with static methods that operate on [RatchetState] + -/// [CCCData]. Designed to run on the background isolate alongside the -/// existing CCC cipher chain. -/// -/// Phase 2 of the Hydra Apocalypse Ratchet. -/// -/// ## Per-Sender Chain Separation -/// -/// Each participant holds a separate [RatchetState] per sender in the -/// channel. The chain key is derived as: -/// -/// ```text -/// rootKey -/// └── KDF("chain|channelUuid|senderIdentifier") → initial chainKey -/// -/// For each message: -/// chainKey = KDF(chainKey, "next|channelUuid") // symmetric ratchet step -/// messageKey = KDF(chainKey, counter + channelUuid) // per-message key -/// ``` -/// -/// Including `senderIdentifier` in the initial derivation guarantees that -/// two senders sharing the same root key and channel produce different -/// chains, preventing key reuse when both send at the same counter. -import 'dart:convert'; - -import 'package:cryptography/cryptography.dart'; - -import 'package:letusmsg/ccc/ccc_kdf.dart'; -import 'package:letusmsg/data/ccc_data.dart'; -import 'package:letusmsg/data/ratchet_state_data.dart'; - -/// Result of a ratchet advance operation. -/// -/// Contains the derived 32-byte base message key and the message counter -/// it corresponds to. -class RatchetAdvanceResult { - /// The derived 32-byte base message key for AEAD encryption/decryption. - /// - /// This key is passed into the isolate worker as the root key for - /// per-layer key derivation (replacing the Phase 1 static root key). - final List baseMessageKey; - - /// The message counter this key corresponds to. - final int counter; - - /// Ephemeral X25519 public key bytes (32 bytes) when an asymmetric ratchet - /// step was performed on this message. The caller must embed this in the - /// encrypted payload (``rk`` field) so receivers can apply the same reset. - /// - /// Null when no asymmetric ratchet step was triggered. - final List? asymmetricRatchetPublicKey; - - const RatchetAdvanceResult({ - required this.baseMessageKey, - required this.counter, - this.asymmetricRatchetPublicKey, - }); -} - -/// Core ratchet engine implementing the symmetric Double Ratchet. -/// -/// All methods are static and pure — they take [RatchetState] and [CCCData] -/// as input, mutate the state in place, and return derived key material. -/// -/// The engine does **not** handle persistence; callers must save the updated -/// [RatchetState] via [RatchetStateManager] after each operation. -/// -/// ## Key Derivation Chain -/// -/// ```text -/// rootKey -/// └── KDF("chain|channelUuid|senderIdentifier") → initial chainKey -/// -/// For each message: -/// chainKey = KDF(chainKey, "next|channelUuid") // symmetric ratchet step -/// messageKey = KDF(chainKey, counter + channelUuid) // per-message key -/// ``` -class RatchetEngine { - /// Default checkpoint interval (messages between chain key snapshots). - static const int defaultCheckpointInterval = 500; - - /// Default asymmetric ratchet frequency (messages between KEM steps). - static const int defaultRatchetFrequency = 50; - - // --------------------------------------------------------------------------- - // Initialization - // --------------------------------------------------------------------------- - - /// Initialize ratchet state from a shared root secret. - /// - /// Called once when a channel is created or an invite is accepted. - /// All parties must call this with the same [rootKey] to establish - /// identical starting states — critical for N-party group channels. - /// - /// Each participant creates one state per sender (including themselves). - /// The [senderIdentifier] is mixed into the chain derivation so that - /// two senders sharing the same root and channel produce **different** - /// chain keys — preventing key reuse when both send the same counter. - /// - /// The [rootKey] should be a 32-byte cryptographically random secret - /// shared securely during the invite flow. - /// - /// Returns a fully initialized [RatchetState] with: - /// - A chain key unique to this (channel, sender) pair - /// - Counters at 0 - /// - Genesis checkpoint at counter 0 - static Future initializeFromRoot({ - required List rootKey, - required String channelUuid, - required String senderIdentifier, - required CCCData cccData, - }) async { - // Derive the chain key from root with sender-specific domain separation. - // Including senderIdentifier ensures that two participants sharing the - // same rootKey + channelUuid produce different chains, eliminating any - // key-reuse risk when both send at the same counter value. - final chainKey = await _kdf( - cccData, - rootKey, - 'chain|$channelUuid|$senderIdentifier', - ); - - final state = RatchetState( - encryptedRootKey: List.from(rootKey), // TODO: encrypt under device master key - chainKey: chainKey, - channelUuid: channelUuid, - senderIdentifier: senderIdentifier, - ); - - // Genesis checkpoint - state.checkpoints[0] = List.from(chainKey); - - return state; - } - - // --------------------------------------------------------------------------- - // Symmetric Chain Advance - // --------------------------------------------------------------------------- - - /// Advance the chain and derive the base message key for sending. - /// - /// This is the "click" of the ratchet. When - /// [CCCData.symmetricRatchetEveryMessage] is true (default), the chain key - /// is replaced with its KDF successor and the old value is permanently lost. - /// - /// The returned [RatchetAdvanceResult.baseMessageKey] is a unique 32-byte - /// key for this specific message, suitable for passing into the isolate - /// worker as the root key for per-layer AEAD derivation. - /// - /// **Side effects**: mutates [state] (chain key, counter, checkpoints). - /// Caller must persist the updated state. - static Future advanceSending({ - required RatchetState state, - required CCCData cccData, - }) async { - final counter = state.lastSentCounter + 1; - - // Symmetric ratchet step: derive new chain key from current - if (cccData.symmetricRatchetEveryMessage) { - state.chainKey = await _kdf( - cccData, - state.chainKey, - 'next|${state.channelUuid}', - ); - } - - // Derive per-message base key - final baseMessageKey = await _deriveMessageKey( - cccData, - state.chainKey, - counter, - state.channelUuid, - ); - - // Update counter - state.lastSentCounter = counter; - - // Checkpoint if needed - _maybeCheckpoint( - state.checkpoints, - counter, - state.chainKey, - cccData.checkpointInterval, - ); - - // Asymmetric ratchet step: generates fresh X25519 keypair and mixes - // entropy into chain. The returned public key must be embedded in the - // message payload ("rk" field) so receivers can apply the same reset. - List? asymmetricPublicKey; - if (_isAsymmetricRatchetDue(counter, cccData.ratchetFrequency)) { - asymmetricPublicKey = await performAsymmetricRatchet( - state: state, - cccData: cccData, - ); - } - - return RatchetAdvanceResult( - baseMessageKey: baseMessageKey, - counter: counter, - asymmetricRatchetPublicKey: asymmetricPublicKey, - ); - } - - /// Advance the chain to match the incoming message counter - /// and derive the base message key for decryption. - /// - /// The chain is fast-forwarded from its current position to - /// [incomingCounter], applying the symmetric ratchet step at each - /// intermediate position. - /// - /// **Side effects**: mutates [state] (chain key, counter, checkpoints). - /// Caller must persist the updated state. - static Future advanceReceiving({ - required RatchetState state, - required CCCData cccData, - required int incomingCounter, - }) async { - // Fast-forward chain to match incoming counter - while (state.lastReceivedCounter < incomingCounter) { - if (cccData.symmetricRatchetEveryMessage) { - state.chainKey = await _kdf( - cccData, - state.chainKey, - 'next|${state.channelUuid}', - ); - } - state.lastReceivedCounter += 1; - - // Checkpoint at intermediate steps too - _maybeCheckpoint( - state.checkpoints, - state.lastReceivedCounter, - state.chainKey, - cccData.checkpointInterval, - ); - } - - // Derive per-message base key - final baseMessageKey = await _deriveMessageKey( - cccData, - state.chainKey, - incomingCounter, - state.channelUuid, - ); - - return RatchetAdvanceResult( - baseMessageKey: baseMessageKey, - counter: incomingCounter, - ); - } - - // --------------------------------------------------------------------------- - // Old Message Decryption (Random Access via Checkpoints) - // --------------------------------------------------------------------------- - - /// Derive the base message key for an older message by replaying the chain - /// from the nearest checkpoint. - /// - /// This is the "scroll up" scenario — the user wants to read a message - /// that was received in the past. Instead of replaying from genesis - /// (which could be millions of steps), we start from the nearest saved - /// checkpoint and replay at most [checkpointInterval] steps. - /// - /// **Does not mutate** the main chain keys or counters in [state]. - /// May add new checkpoints to [state.checkpoints]. - static Future deriveKeyForOldMessage({ - required RatchetState state, - required CCCData cccData, - required int targetCounter, - }) async { - // Find nearest checkpoint at or before targetCounter - int checkpointCounter = 0; - List chainKey = List.from(state.checkpoints[0] ?? state.chainKey); - - final sortedKeys = state.checkpoints.keys.toList()..sort(); - for (final cp in sortedKeys) { - if (cp <= targetCounter) { - checkpointCounter = cp; - chainKey = List.from(state.checkpoints[cp]!); - } else { - break; - } - } - - // Replay chain forward from checkpoint to target - int current = checkpointCounter; - while (current < targetCounter) { - if (cccData.symmetricRatchetEveryMessage) { - chainKey = await _kdf( - cccData, - chainKey, - 'next|${state.channelUuid}', - ); - } - current += 1; - } - - // Derive base_message_key at target - final baseMessageKey = await _deriveMessageKey( - cccData, - chainKey, - targetCounter, - state.channelUuid, - ); - - // Optionally save a new checkpoint - final interval = cccData.checkpointInterval > 0 - ? cccData.checkpointInterval - : defaultCheckpointInterval; - if (targetCounter % interval == 0 && - !state.checkpoints.containsKey(targetCounter)) { - state.checkpoints[targetCounter] = List.from(chainKey); - } - - return RatchetAdvanceResult( - baseMessageKey: baseMessageKey, - counter: targetCounter, - ); - } - - // --------------------------------------------------------------------------- - // Asymmetric Ratchet (KEM) – Phase 3 X25519 - // --------------------------------------------------------------------------- - - /// Perform an asymmetric ratchet step on the **sending** chain. - /// - /// Generates a fresh X25519 keypair and mixes the public key bytes into - /// the chain key via KDF. The public key is returned so the caller can - /// embed it in the encrypted payload (``rk`` field). All receivers - /// extract those same bytes and call [applyRemoteAsymmetricRatchet] to - /// perform the identical chain reset. - /// - /// ```text - /// freshKeyPair = X25519.newKeyPair() - /// publicKeyBytes = freshKeyPair.publicKey.bytes // 32 bytes - /// - /// new_chain_key = KDF( - /// old_chain_key || publicKeyBytes, - /// "asymmetric-reset|" + channelUuid, - /// ) - /// ``` - /// - /// The DH private key is persisted in [state] for potential future - /// pairwise DH key agreement (Phase 4 enhancement for 1-to-1 channels). - /// - /// Returns the 32-byte X25519 public key that must be embedded in the - /// message payload. - static Future> performAsymmetricRatchet({ - required RatchetState state, - required CCCData cccData, - }) async { - // 1. Generate fresh X25519 keypair (32 bytes, OS-level CSPRNG) - final x25519 = X25519(); - final keyPair = await x25519.newKeyPair(); - final publicKey = await keyPair.extractPublicKey(); - final privateKeyBytes = await keyPair.extractPrivateKeyBytes(); - final publicKeyBytes = publicKey.bytes; - - // 2. Mix public-key entropy into the chain - // Using the public key ensures all receivers (group-compatible) can - // compute the same new chain key from information in the payload. - state.chainKey = await _kdf( - cccData, - [...state.chainKey, ...publicKeyBytes], - 'asymmetric-reset|${state.channelUuid}', - ); - - // 3. Persist DH keys for future pairwise DH (Phase 4) - state.dhPrivateKey = privateKeyBytes; - state.dhPublicKey = List.from(publicKeyBytes); - state.lastAsymmetricRatchetCounter = state.lastSentCounter; - - return List.from(publicKeyBytes); - } - - /// Apply a remote asymmetric ratchet step on the **receiving** chain. - /// - /// Called by the message processor after successful decryption when - /// the payload contains an ``rk`` (ratchet-key) field. Applies the - /// same chain-key mixing as [performAsymmetricRatchet] so sender and - /// receiver chains stay in sync. - /// - /// [remotePublicKeyBytes] is the 32-byte X25519 public key extracted - /// from the decrypted payload. - static Future applyRemoteAsymmetricRatchet({ - required RatchetState state, - required CCCData cccData, - required List remotePublicKeyBytes, - }) async { - // Mix the same public-key entropy that the sender used - state.chainKey = await _kdf( - cccData, - [...state.chainKey, ...remotePublicKeyBytes], - 'asymmetric-reset|${state.channelUuid}', - ); - - // Store remote public key for future DH (Phase 4) - state.remoteDhPublicKey = List.from(remotePublicKeyBytes); - state.lastAsymmetricRatchetCounter = state.lastReceivedCounter; - } - - /// Check whether an asymmetric ratchet step is due at the given counter. - static bool _isAsymmetricRatchetDue(int counter, int ratchetFrequency) { - if (ratchetFrequency <= 0) return false; // disabled or every-message (handled separately) - return counter > 0 && counter % ratchetFrequency == 0; - } - - // --------------------------------------------------------------------------- - // Key Derivation Functions (Internal) - // --------------------------------------------------------------------------- - - /// Core KDF: derive 32-byte key material from input key + info string. - /// - /// Uses the KDF function selected in [CCCData.kdfFunction] - /// (SHA-256/384/512/BLAKE2b-512). Output is always truncated to 32 bytes. - static Future> _kdf( - CCCData cccData, - List inputKey, - String info, - ) async { - final kdfFunction = cccKdfFunctionFromInt( - normalizeCccKdfFunctionValue(cccData.kdfFunction), - ); - final hashInput = [...inputKey, ...utf8.encode(info)]; - final fullHash = await _hashBytes(hashInput, kdfFunction); - return fullHash.sublist(0, 32); // truncate to 32 bytes - } - - /// Derive per-message encryption key from chain key + counter + channel ID. - /// - /// Formula: ``KDF(chainKey, counter_bytes(8) || channelUuid)`` - /// - /// The counter is encoded as 8-byte big-endian to ensure deterministic - /// byte representation across platforms. - static Future> _deriveMessageKey( - CCCData cccData, - List chainKey, - int counter, - String channelUuid, - ) async { - final counterBytes = _intToBytes8(counter); - final info = '$channelUuid|msg|${String.fromCharCodes(counterBytes)}'; - return _kdf(cccData, chainKey, info); - } - - /// Hash bytes using the specified KDF/hash function. - static Future> _hashBytes( - List bytes, - CccKdfFunction kdfFunction, - ) async { - switch (kdfFunction) { - case CccKdfFunction.sha256: - return (await Sha256().hash(bytes)).bytes; - case CccKdfFunction.sha384: - return (await Sha384().hash(bytes)).bytes; - case CccKdfFunction.sha512: - return (await Sha512().hash(bytes)).bytes; - case CccKdfFunction.blake2b512: - return (await Blake2b().hash(bytes)).bytes; - } - } - - /// Convert an integer to 8-byte big-endian representation. - static List _intToBytes8(int value) { - return [ - (value >> 56) & 0xFF, - (value >> 48) & 0xFF, - (value >> 40) & 0xFF, - (value >> 32) & 0xFF, - (value >> 24) & 0xFF, - (value >> 16) & 0xFF, - (value >> 8) & 0xFF, - value & 0xFF, - ]; - } - - // --------------------------------------------------------------------------- - // Checkpoint Helpers - // --------------------------------------------------------------------------- - - /// Save a checkpoint if the counter is at a checkpoint boundary. - static void _maybeCheckpoint( - Map> checkpoints, - int counter, - List chainKey, - int checkpointInterval, - ) { - final interval = - checkpointInterval > 0 ? checkpointInterval : defaultCheckpointInterval; - if (counter % interval == 0) { - checkpoints[counter] = List.from(chainKey); - } - } -} diff --git a/flutter_src/ccc/ratchet_state_manager.dart b/flutter_src/ccc/ratchet_state_manager.dart deleted file mode 100644 index 6a6185e..0000000 --- a/flutter_src/ccc/ratchet_state_manager.dart +++ /dev/null @@ -1,154 +0,0 @@ -/// -/// Ratchet State Manager – Hive Persistence for Ratchet Chain State -/// -/// Manages the lifecycle of [RatchetState] objects in a dedicated Hive box. -/// Each entry is keyed by ``'{channelUuid}_{senderIdentifier}'``. -/// -/// Phase 2 of the Hydra Apocalypse Ratchet. -/// -import 'package:hive_ce/hive.dart'; -import 'package:letusmsg/data/ratchet_state_data.dart'; -import 'package:letusmsg/utilz/Llog.dart'; - -/// Manages persistence of [RatchetState] objects in Hive. -/// -/// Provides CRUD operations for ratchet states and channel-level cleanup. -/// The box is opened lazily on first access and remains open for the app -/// lifetime. -/// -/// ## Key Format -/// ``'{channelUuid}_{senderIdentifier}'`` — deterministic from the -/// [RatchetState.hiveKey] property. -/// -/// ## Usage -/// ```dart -/// final manager = RatchetStateManager(); -/// await manager.open(); -/// -/// // Save after ratchet advance -/// await manager.save(state); -/// -/// // Load for decrypt -/// final state = await manager.load('chan-uuid', 'sender-id'); -/// ``` -class RatchetStateManager { - static const String boxName = 'ratchet_state'; - - Box? _box; - - /// Whether the Hive box is currently open. - bool get isOpen => _box?.isOpen ?? false; - - /// Open the ratchet state Hive box. - /// - /// Safe to call multiple times — returns immediately if already open. - Future open() async { - if (_box != null && _box!.isOpen) return; - try { - _box = await Hive.openBox(boxName); - } catch (ex) { - Llog.log.e('[RatchetStateManager] Failed to open box: $ex'); - rethrow; - } - } - - /// Ensure the box is open, opening it if necessary. - Future> _ensureBox() async { - if (_box == null || !_box!.isOpen) { - await open(); - } - return _box!; - } - - /// Load ratchet state for a specific channel + sender. - /// - /// Returns ``null`` if no state exists (channel not yet initialized with - /// ratchet, or pre-Phase 2 channel). - Future load( - String channelUuid, - String senderIdentifier, - ) async { - final box = await _ensureBox(); - final key = _buildKey(channelUuid, senderIdentifier); - return box.get(key); - } - - /// Save ratchet state after advancing the chain. - /// - /// Must be called after every send/receive operation to persist the - /// updated chain keys and counters. - Future save(RatchetState state) async { - final box = await _ensureBox(); - await box.put(state.hiveKey, state); - } - - /// Delete ratchet state for a specific channel + sender. - Future delete( - String channelUuid, - String senderIdentifier, - ) async { - final box = await _ensureBox(); - final key = _buildKey(channelUuid, senderIdentifier); - await box.delete(key); - } - - /// Delete all ratchet states for a channel (all senders). - /// - /// Called when a channel is deleted or left. Iterates all keys in the box - /// and removes those matching the channel prefix. - Future deleteChannel(String channelUuid) async { - final box = await _ensureBox(); - final prefix = '${channelUuid}_'; - final keysToDelete = []; - for (final key in box.keys) { - if (key.toString().startsWith(prefix)) { - keysToDelete.add(key); - } - } - if (keysToDelete.isNotEmpty) { - await box.deleteAll(keysToDelete); - Llog.log.d('[RatchetStateManager] Deleted ${keysToDelete.length} ' - 'ratchet state(s) for channel $channelUuid'); - } - } - - /// List all ratchet states for a channel (all senders). - /// - /// Useful for debugging and testing. - Future> listForChannel(String channelUuid) async { - final box = await _ensureBox(); - final prefix = '${channelUuid}_'; - final results = []; - for (final key in box.keys) { - if (key.toString().startsWith(prefix)) { - final state = box.get(key); - if (state != null) results.add(state); - } - } - return results; - } - - /// Check if a ratchet state exists for a channel + sender. - Future exists( - String channelUuid, - String senderIdentifier, - ) async { - final box = await _ensureBox(); - return box.containsKey(_buildKey(channelUuid, senderIdentifier)); - } - - /// Close the Hive box. - /// - /// Called during app shutdown or cleanup. - Future close() async { - if (_box != null && _box!.isOpen) { - await _box!.close(); - } - _box = null; - } - - /// Build the composite Hive key from channel + sender identifiers. - static String _buildKey(String channelUuid, String senderIdentifier) { - return '${channelUuid}_$senderIdentifier'; - } -}