From f3bb3b814bab246b86a50415fff16800afef20b1 Mon Sep 17 00:00:00 2001 From: "cto-new[bot]" <140088366+cto-new[bot]@users.noreply.github.com> Date: Fri, 12 Dec 2025 14:05:54 +0000 Subject: [PATCH] refactor(frackture): convert monolithic script into a package with modular design and unified API --- __pycache__/frackture (2).cpython-312.pyc | Bin 0 -> 6737 bytes compressed.json | 34 ++ decrypted_vector.txt | 1 + encrypted.json | 34 ++ fingerprint.txt | 1 + frackture/__init__.py | 246 +++++++++++ frackture/__main__.py | 12 + .../__pycache__/__init__.cpython-312.pyc | Bin 0 -> 6796 bytes .../__pycache__/__main__.cpython-312.pyc | Bin 0 -> 458 bytes frackture/__pycache__/cli.cpython-312.pyc | Bin 0 -> 15086 bytes frackture/__pycache__/engine.cpython-312.pyc | Bin 0 -> 14908 bytes frackture/__pycache__/entropy.cpython-312.pyc | Bin 0 -> 8553 bytes frackture/__pycache__/models.cpython-312.pyc | Bin 0 -> 4962 bytes .../__pycache__/preprocess.cpython-312.pyc | Bin 0 -> 4682 bytes .../__pycache__/symbolic.cpython-312.pyc | Bin 0 -> 8805 bytes frackture/cli.py | 292 +++++++++++++ frackture/engine.py | 412 ++++++++++++++++++ frackture/entropy.py | 245 +++++++++++ frackture/models.py | 113 +++++ frackture/preprocess.py | 108 +++++ frackture/symbolic.py | 207 +++++++++ key.txt | 1 + secret_input.txt | 1 + test_input.txt | 1 + 24 files changed, 1708 insertions(+) create mode 100644 __pycache__/frackture (2).cpython-312.pyc create mode 100644 compressed.json create mode 100644 decrypted_vector.txt create mode 100644 encrypted.json create mode 100644 fingerprint.txt create mode 100644 frackture/__init__.py create mode 100644 frackture/__main__.py create mode 100644 frackture/__pycache__/__init__.cpython-312.pyc create mode 100644 frackture/__pycache__/__main__.cpython-312.pyc create mode 100644 frackture/__pycache__/cli.cpython-312.pyc create mode 100644 frackture/__pycache__/engine.cpython-312.pyc create mode 100644 frackture/__pycache__/entropy.cpython-312.pyc create mode 100644 frackture/__pycache__/models.cpython-312.pyc create mode 100644 frackture/__pycache__/preprocess.cpython-312.pyc create mode 100644 frackture/__pycache__/symbolic.cpython-312.pyc create mode 100644 frackture/cli.py create mode 100644 frackture/engine.py create mode 100644 frackture/entropy.py create mode 100644 frackture/models.py create mode 100644 frackture/preprocess.py create mode 100644 frackture/symbolic.py create mode 100644 key.txt create mode 100644 secret_input.txt create mode 100644 test_input.txt diff --git a/__pycache__/frackture (2).cpython-312.pyc b/__pycache__/frackture (2).cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..28bc0a487adaf345ca0c0def83bd67c13e75c226 GIT binary patch literal 6737 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 Ap#T5? literal 0 HcmV?d00001 diff --git a/compressed.json b/compressed.json new file mode 100644 index 0000000..59234c9 --- /dev/null +++ b/compressed.json @@ -0,0 +1,34 @@ +{ + "symbolic": "00408040004080c000400080c000c0004080400040004080c000400080c000c0", + "entropy": [ + 13.335411071777344, + 41.52340316772461, + 1.1188021898269653, + 0.8959053158760071, + 7.063382625579834, + 7.167986869812012, + 2.464329481124878, + 1.4854254722595215, + 1.220164179801941, + 1.1779710054397583, + 2.84759783744812, + 6.463021278381348, + 1.7775392532348633, + 1.6017292737960815, + 4.298604965209961, + 4.052870750427246 + ], + "metadata": { + "version": "3.3", + "passes": 4, + "target_length": 768, + "optimization_trials": 0, + "created_at": "1765548231" + }, + "encryption": { + "mode": "none", + "key_id": null, + "salt": null + }, + "fingerprint": "6d4e484b928c50ac" +} \ No newline at end of file diff --git a/decrypted_vector.txt b/decrypted_vector.txt new file mode 100644 index 0000000..6bf706f --- /dev/null +++ b/decrypted_vector.txt @@ -0,0 +1 @@ +[0.6141611337661743, 0.2549768388271332, 0.6192259192466736, 0.250980406999588, 0.6254901885986328, 0.2581024467945099, 0.6221581101417542, 0.25129926204681396, 0.48893752694129944, 0.3835547864437103, 0.8696731328964233, 0.12601235508918762, 0.7241905927658081, 0.1369626373052597, 0.7495142817497253, 0.0008079208782874048, 0.8651415109634399, 0.380467027425766, 0.6192259192466736, 0.250980406999588, 0.6254901885986328, 0.2581024467945099, 0.49666792154312134, 0.3767894506454468, 0.8654081225395203, 0.1325744092464447, 0.7441829442977905, 0.12601235508918762, 0.7241905927658081, 0.011472432874143124, 0.8750044703483582, 0.37727850675582886, 0.6141611337661743, 0.2549768388271332, 0.6192259192466736, 0.250980406999588, 0.6254901885986328, 0.2581024467945099, 0.6221581101417542, 0.25129926204681396, 0.48893752694129944, 0.3835547864437103, 0.8696731328964233, 0.12601235508918762, 0.7241905927658081, 0.1369626373052597, 0.7495142817497253, 0.0008079208782874048, 0.8651415109634399, 0.380467027425766, 0.6192259192466736, 0.250980406999588, 0.6254901885986328, 0.2581024467945099, 0.49666792154312134, 0.3767894506454468, 0.8654081225395203, 0.1325744092464447, 0.7441829442977905, 0.12601235508918762, 0.7241905927658081, 0.011472432874143124, 0.8750044703483582, 0.37727850675582886, 0.6141611337661743, 0.2549768388271332, 0.6192259192466736, 0.250980406999588, 0.6254901885986328, 0.2581024467945099, 0.6221581101417542, 0.25129926204681396, 0.48893752694129944, 0.3835547864437103, 0.8696731328964233, 0.12601235508918762, 0.7241905927658081, 0.1369626373052597, 0.7495142817497253, 0.0008079208782874048, 0.8651415109634399, 0.380467027425766, 0.6192259192466736, 0.250980406999588, 0.6254901885986328, 0.2581024467945099, 0.49666792154312134, 0.3767894506454468, 0.8654081225395203, 0.1325744092464447, 0.7441829442977905, 0.12601235508918762, 0.7241905927658081, 0.011472432874143124, 0.8750044703483582, 0.37727850675582886, 0.6141611337661743, 0.2549768388271332, 0.6192259192466736, 0.250980406999588, 0.6254901885986328, 0.2581024467945099, 0.6221581101417542, 0.25129926204681396, 0.48893752694129944, 0.3835547864437103, 0.8696731328964233, 0.12601235508918762, 0.7241905927658081, 0.1369626373052597, 0.7495142817497253, 0.0008079208782874048, 0.8651415109634399, 0.380467027425766, 0.6192259192466736, 0.250980406999588, 0.6254901885986328, 0.2581024467945099, 0.49666792154312134, 0.3767894506454468, 0.8654081225395203, 0.1325744092464447, 0.7441829442977905, 0.12601235508918762, 0.7241905927658081, 0.011472432874143124, 0.8750044703483582, 0.37727850675582886, 0.6141611337661743, 0.2549768388271332, 0.6192259192466736, 0.250980406999588, 0.6254901885986328, 0.2581024467945099, 0.6221581101417542, 0.25129926204681396, 0.48893752694129944, 0.3835547864437103, 0.8696731328964233, 0.12601235508918762, 0.7241905927658081, 0.1369626373052597, 0.7495142817497253, 0.0008079208782874048, 0.8651415109634399, 0.380467027425766, 0.6192259192466736, 0.250980406999588, 0.6254901885986328, 0.2581024467945099, 0.49666792154312134, 0.3767894506454468, 0.8654081225395203, 0.1325744092464447, 0.7441829442977905, 0.12601235508918762, 0.7241905927658081, 0.011472432874143124, 0.8750044703483582, 0.37727850675582886, 0.6141611337661743, 0.2549768388271332, 0.6192259192466736, 0.250980406999588, 0.6254901885986328, 0.2581024467945099, 0.6221581101417542, 0.25129926204681396, 0.48893752694129944, 0.3835547864437103, 0.8696731328964233, 0.12601235508918762, 0.7241905927658081, 0.1369626373052597, 0.7495142817497253, 0.0008079208782874048, 0.8651415109634399, 0.380467027425766, 0.6192259192466736, 0.250980406999588, 0.6254901885986328, 0.2581024467945099, 0.49666792154312134, 0.3767894506454468, 0.8654081225395203, 0.1325744092464447, 0.7441829442977905, 0.12601235508918762, 0.7241905927658081, 0.011472432874143124, 0.8750044703483582, 0.37727850675582886, 0.6141611337661743, 0.2549768388271332, 0.6192259192466736, 0.250980406999588, 0.6254901885986328, 0.2581024467945099, 0.6221581101417542, 0.25129926204681396, 0.48893752694129944, 0.3835547864437103, 0.8696731328964233, 0.12601235508918762, 0.7241905927658081, 0.1369626373052597, 0.7495142817497253, 0.0008079208782874048, 0.8651415109634399, 0.380467027425766, 0.6192259192466736, 0.250980406999588, 0.6254901885986328, 0.2581024467945099, 0.49666792154312134, 0.3767894506454468, 0.8654081225395203, 0.1325744092464447, 0.7441829442977905, 0.12601235508918762, 0.7241905927658081, 0.011472432874143124, 0.8750044703483582, 0.37727850675582886, 0.6141611337661743, 0.2549768388271332, 0.6192259192466736, 0.250980406999588, 0.6254901885986328, 0.2581024467945099, 0.6221581101417542, 0.25129926204681396, 0.48893752694129944, 0.3835547864437103, 0.8696731328964233, 0.12601235508918762, 0.7241905927658081, 0.1369626373052597, 0.7495142817497253, 0.0008079208782874048, 0.8651415109634399, 0.380467027425766, 0.6192259192466736, 0.250980406999588, 0.6254901885986328, 0.2581024467945099, 0.49666792154312134, 0.3767894506454468, 0.8654081225395203, 0.1325744092464447, 0.7441829442977905, 0.12601235508918762, 0.7241905927658081, 0.011472432874143124, 0.8750044703483582, 0.37727850675582886, 0.6141611337661743, 0.2549768388271332, 0.6192259192466736, 0.250980406999588, 0.6254901885986328, 0.2581024467945099, 0.6221581101417542, 0.25129926204681396, 0.48893752694129944, 0.3835547864437103, 0.8696731328964233, 0.12601235508918762, 0.7241905927658081, 0.1369626373052597, 0.7495142817497253, 0.0008079208782874048, 0.8651415109634399, 0.380467027425766, 0.6192259192466736, 0.250980406999588, 0.6254901885986328, 0.2581024467945099, 0.49666792154312134, 0.3767894506454468, 0.8654081225395203, 0.1325744092464447, 0.7441829442977905, 0.12601235508918762, 0.7241905927658081, 0.011472432874143124, 0.8750044703483582, 0.37727850675582886, 0.6141611337661743, 0.2549768388271332, 0.6192259192466736, 0.250980406999588, 0.6254901885986328, 0.2581024467945099, 0.6221581101417542, 0.25129926204681396, 0.48893752694129944, 0.3835547864437103, 0.8696731328964233, 0.12601235508918762, 0.7241905927658081, 0.1369626373052597, 0.7495142817497253, 0.0008079208782874048, 0.8651415109634399, 0.380467027425766, 0.6192259192466736, 0.250980406999588, 0.6254901885986328, 0.2581024467945099, 0.49666792154312134, 0.3767894506454468, 0.8654081225395203, 0.1325744092464447, 0.7441829442977905, 0.12601235508918762, 0.7241905927658081, 0.011472432874143124, 0.8750044703483582, 0.37727850675582886, 0.6141611337661743, 0.2549768388271332, 0.6192259192466736, 0.250980406999588, 0.6254901885986328, 0.2581024467945099, 0.6221581101417542, 0.25129926204681396, 0.48893752694129944, 0.3835547864437103, 0.8696731328964233, 0.12601235508918762, 0.7241905927658081, 0.1369626373052597, 0.7495142817497253, 0.0008079208782874048, 0.8651415109634399, 0.380467027425766, 0.6192259192466736, 0.250980406999588, 0.6254901885986328, 0.2581024467945099, 0.49666792154312134, 0.3767894506454468, 0.8654081225395203, 0.1325744092464447, 0.7441829442977905, 0.12601235508918762, 0.7241905927658081, 0.011472432874143124, 0.8750044703483582, 0.37727850675582886, 0.6141611337661743, 0.2549768388271332, 0.6192259192466736, 0.250980406999588, 0.6254901885986328, 0.2581024467945099, 0.6221581101417542, 0.25129926204681396, 0.48893752694129944, 0.3835547864437103, 0.8696731328964233, 0.12601235508918762, 0.7241905927658081, 0.1369626373052597, 0.7495142817497253, 0.0008079208782874048, 0.8651415109634399, 0.380467027425766, 0.6192259192466736, 0.250980406999588, 0.6254901885986328, 0.2581024467945099, 0.49666792154312134, 0.3767894506454468, 0.8654081225395203, 0.1325744092464447, 0.7441829442977905, 0.12601235508918762, 0.7241905927658081, 0.011472432874143124, 0.8750044703483582, 0.37727850675582886, 0.6141611337661743, 0.2549768388271332, 0.6192259192466736, 0.250980406999588, 0.6254901885986328, 0.2581024467945099, 0.6221581101417542, 0.25129926204681396, 0.48893752694129944, 0.3835547864437103, 0.8696731328964233, 0.12601235508918762, 0.7241905927658081, 0.1369626373052597, 0.7495142817497253, 0.0008079208782874048, 0.8651415109634399, 0.380467027425766, 0.6192259192466736, 0.250980406999588, 0.6254901885986328, 0.2581024467945099, 0.49666792154312134, 0.3767894506454468, 0.8654081225395203, 0.1325744092464447, 0.7441829442977905, 0.12601235508918762, 0.7241905927658081, 0.011472432874143124, 0.8750044703483582, 0.37727850675582886, 0.6141611337661743, 0.2549768388271332, 0.6192259192466736, 0.250980406999588, 0.6254901885986328, 0.2581024467945099, 0.6221581101417542, 0.25129926204681396, 0.48893752694129944, 0.3835547864437103, 0.8696731328964233, 0.12601235508918762, 0.7241905927658081, 0.1369626373052597, 0.7495142817497253, 0.0008079208782874048, 0.8651415109634399, 0.380467027425766, 0.6192259192466736, 0.250980406999588, 0.6254901885986328, 0.2581024467945099, 0.49666792154312134, 0.3767894506454468, 0.8654081225395203, 0.1325744092464447, 0.7441829442977905, 0.12601235508918762, 0.7241905927658081, 0.011472432874143124, 0.8750044703483582, 0.37727850675582886, 0.6141611337661743, 0.2549768388271332, 0.6192259192466736, 0.250980406999588, 0.6254901885986328, 0.2581024467945099, 0.6221581101417542, 0.25129926204681396, 0.48893752694129944, 0.3835547864437103, 0.8696731328964233, 0.12601235508918762, 0.7241905927658081, 0.1369626373052597, 0.7495142817497253, 0.0008079208782874048, 0.8651415109634399, 0.380467027425766, 0.6192259192466736, 0.250980406999588, 0.6254901885986328, 0.2581024467945099, 0.49666792154312134, 0.3767894506454468, 0.8654081225395203, 0.1325744092464447, 0.7441829442977905, 0.12601235508918762, 0.7241905927658081, 0.011472432874143124, 0.8750044703483582, 0.37727850675582886, 0.6141611337661743, 0.2549768388271332, 0.6192259192466736, 0.250980406999588, 0.6254901885986328, 0.2581024467945099, 0.6221581101417542, 0.25129926204681396, 0.48893752694129944, 0.3835547864437103, 0.8696731328964233, 0.12601235508918762, 0.7241905927658081, 0.1369626373052597, 0.7495142817497253, 0.0008079208782874048, 0.8651415109634399, 0.380467027425766, 0.6192259192466736, 0.250980406999588, 0.6254901885986328, 0.2581024467945099, 0.49666792154312134, 0.3767894506454468, 0.8654081225395203, 0.1325744092464447, 0.7441829442977905, 0.12601235508918762, 0.7241905927658081, 0.011472432874143124, 0.8750044703483582, 0.37727850675582886, 0.6141611337661743, 0.2549768388271332, 0.6192259192466736, 0.250980406999588, 0.6254901885986328, 0.2581024467945099, 0.6221581101417542, 0.25129926204681396, 0.48893752694129944, 0.3835547864437103, 0.8696731328964233, 0.12601235508918762, 0.7241905927658081, 0.1369626373052597, 0.7495142817497253, 0.0008079208782874048, 0.8651415109634399, 0.380467027425766, 0.6192259192466736, 0.250980406999588, 0.6254901885986328, 0.2581024467945099, 0.49666792154312134, 0.3767894506454468, 0.8654081225395203, 0.1325744092464447, 0.7441829442977905, 0.12601235508918762, 0.7241905927658081, 0.011472432874143124, 0.8750044703483582, 0.37727850675582886, 0.6141611337661743, 0.2549768388271332, 0.6192259192466736, 0.250980406999588, 0.6254901885986328, 0.2581024467945099, 0.6221581101417542, 0.25129926204681396, 0.48893752694129944, 0.3835547864437103, 0.8696731328964233, 0.12601235508918762, 0.7241905927658081, 0.1369626373052597, 0.7495142817497253, 0.0008079208782874048, 0.8651415109634399, 0.380467027425766, 0.6192259192466736, 0.250980406999588, 0.6254901885986328, 0.2581024467945099, 0.49666792154312134, 0.3767894506454468, 0.8654081225395203, 0.1325744092464447, 0.7441829442977905, 0.12601235508918762, 0.7241905927658081, 0.011472432874143124, 0.8750044703483582, 0.37727850675582886, 0.6141611337661743, 0.2549768388271332, 0.6192259192466736, 0.250980406999588, 0.6254901885986328, 0.2581024467945099, 0.6221581101417542, 0.25129926204681396, 0.48893752694129944, 0.3835547864437103, 0.8696731328964233, 0.12601235508918762, 0.7241905927658081, 0.1369626373052597, 0.7495142817497253, 0.0008079208782874048, 0.8651415109634399, 0.380467027425766, 0.6192259192466736, 0.250980406999588, 0.6254901885986328, 0.2581024467945099, 0.49666792154312134, 0.3767894506454468, 0.8654081225395203, 0.1325744092464447, 0.7441829442977905, 0.12601235508918762, 0.7241905927658081, 0.011472432874143124, 0.8750044703483582, 0.37727850675582886, 0.6141611337661743, 0.2549768388271332, 0.6192259192466736, 0.250980406999588, 0.6254901885986328, 0.2581024467945099, 0.6221581101417542, 0.25129926204681396, 0.48893752694129944, 0.3835547864437103, 0.8696731328964233, 0.12601235508918762, 0.7241905927658081, 0.1369626373052597, 0.7495142817497253, 0.0008079208782874048, 0.8651415109634399, 0.380467027425766, 0.6192259192466736, 0.250980406999588, 0.6254901885986328, 0.2581024467945099, 0.49666792154312134, 0.3767894506454468, 0.8654081225395203, 0.1325744092464447, 0.7441829442977905, 0.12601235508918762, 0.7241905927658081, 0.011472432874143124, 0.8750044703483582, 0.37727850675582886, 0.6141611337661743, 0.2549768388271332, 0.6192259192466736, 0.250980406999588, 0.6254901885986328, 0.2581024467945099, 0.6221581101417542, 0.25129926204681396, 0.48893752694129944, 0.3835547864437103, 0.8696731328964233, 0.12601235508918762, 0.7241905927658081, 0.1369626373052597, 0.7495142817497253, 0.0008079208782874048, 0.8651415109634399, 0.380467027425766, 0.6192259192466736, 0.250980406999588, 0.6254901885986328, 0.2581024467945099, 0.49666792154312134, 0.3767894506454468, 0.8654081225395203, 0.1325744092464447, 0.7441829442977905, 0.12601235508918762, 0.7241905927658081, 0.011472432874143124, 0.8750044703483582, 0.37727850675582886, 0.6141611337661743, 0.2549768388271332, 0.6192259192466736, 0.250980406999588, 0.6254901885986328, 0.2581024467945099, 0.6221581101417542, 0.25129926204681396, 0.48893752694129944, 0.3835547864437103, 0.8696731328964233, 0.12601235508918762, 0.7241905927658081, 0.1369626373052597, 0.7495142817497253, 0.0008079208782874048, 0.8651415109634399, 0.380467027425766, 0.6192259192466736, 0.250980406999588, 0.6254901885986328, 0.2581024467945099, 0.49666792154312134, 0.3767894506454468, 0.8654081225395203, 0.1325744092464447, 0.7441829442977905, 0.12601235508918762, 0.7241905927658081, 0.011472432874143124, 0.8750044703483582, 0.37727850675582886, 0.6141611337661743, 0.2549768388271332, 0.6192259192466736, 0.250980406999588, 0.6254901885986328, 0.2581024467945099, 0.6221581101417542, 0.25129926204681396, 0.48893752694129944, 0.3835547864437103, 0.8696731328964233, 0.12601235508918762, 0.7241905927658081, 0.1369626373052597, 0.7495142817497253, 0.0008079208782874048, 0.8651415109634399, 0.380467027425766, 0.6192259192466736, 0.250980406999588, 0.6254901885986328, 0.2581024467945099, 0.49666792154312134, 0.3767894506454468, 0.8654081225395203, 0.1325744092464447, 0.7441829442977905, 0.12601235508918762, 0.7241905927658081, 0.011472432874143124, 0.8750044703483582, 0.37727850675582886, 0.6141611337661743, 0.2549768388271332, 0.6192259192466736, 0.250980406999588, 0.6254901885986328, 0.2581024467945099, 0.6221581101417542, 0.25129926204681396, 0.48893752694129944, 0.3835547864437103, 0.8696731328964233, 0.12601235508918762, 0.7241905927658081, 0.1369626373052597, 0.7495142817497253, 0.0008079208782874048, 0.8651415109634399, 0.380467027425766, 0.6192259192466736, 0.250980406999588, 0.6254901885986328, 0.2581024467945099, 0.49666792154312134, 0.3767894506454468, 0.8654081225395203, 0.1325744092464447, 0.7441829442977905, 0.12601235508918762, 0.7241905927658081, 0.011472432874143124, 0.8750044703483582, 0.37727850675582886] \ No newline at end of file diff --git a/encrypted.json b/encrypted.json new file mode 100644 index 0000000..c11a4c0 --- /dev/null +++ b/encrypted.json @@ -0,0 +1,34 @@ +{ + "symbolic": "408040804080408000c0c04080408000c0c04080408000c0c04080408000c0c0", + "entropy": [ + 0.3620098039215686, + 0.06491493789707584, + 0.36511437908496736, + 0.06246521469937504, + 0.3689542483660131, + 0.06683086437031346, + 0.3669117647058824, + 0.0626606691082609, + 0.3621732026143791, + 0.06680767668749768, + 0.36478758169934644, + 0.0627852832704965, + 0.3525326797385621, + 0.06949756474671824, + 0.3680555555555556, + 0.06296045250732021 + ], + "metadata": { + "version": "3.3", + "passes": 4, + "target_length": 768, + "optimization_trials": 0, + "created_at": "1765548281" + }, + "encryption": { + "mode": "xor", + "key_id": null, + "salt": "6d792d7365637265" + }, + "fingerprint": "93e039a093bfa345" +} \ No newline at end of file diff --git a/fingerprint.txt b/fingerprint.txt new file mode 100644 index 0000000..c718e06 --- /dev/null +++ b/fingerprint.txt @@ -0,0 +1 @@ +00408040004080c000400080c000c0004080400040004080c000400080c000c0 \ No newline at end of file diff --git a/frackture/__init__.py b/frackture/__init__.py new file mode 100644 index 0000000..7349129 --- /dev/null +++ b/frackture/__init__.py @@ -0,0 +1,246 @@ +""" +Frackture - Symbolic compression and fingerprinting engine. + +This package provides a unified API for data compression, encryption, +and fingerprinting using a dual-channel approach combining symbolic +and entropy channels. + +Basic Usage: + from frackture import compress, decompress + + data = b"Hello world" + compressed = compress(data) + original = decompress(compressed) + +Advanced Usage: + from frackture import FracktureEngine + + engine = FracktureEngine() + result = engine.compress(data, optimize=True) + vector = engine.decompress(result.payload) + + # For encryption + encrypted = engine.encrypt(data, key_material=b"my-secret-key") + decrypted = engine.decrypt(encrypted.payload, key_material=b"my-secret-key") + + # For fingerprinting only + fingerprint = engine.fingerprint(data) +""" + +# Version information +__version__ = "3.3.0" +__author__ = "Frackture Development Team" + +# Import public API +from .engine import FracktureEngine +from .models import ( + FrackturePayload, + CompressionMetadata, + EncryptionMetadata, + CompressionResult, + FracktureVersion, + EncryptionMode +) + +# Import core functions for convenience +from .preprocess import frackture_preprocess_universal_v2_6 +from .symbolic import ( + symbolic_channel_encode, + symbolic_channel_decode, + symbolic_fingerprint_with_key +) +from .entropy import ( + entropy_channel_encode, + entropy_channel_decode, + entropy_signature_with_key +) + +# Global engine instance for convenience functions +_global_engine = FracktureEngine() + + +def compress( + data, + passes: int = None, + optimize: bool = False, + num_trials: int = 5 +): + """ + Compress data using Frackture's default engine. + + Args: + data: Input data of any supported type + passes: Number of symbolic passes (default: 4) + optimize: Whether to use optimization (default: False) + num_trials: Number of optimization trials (default: 5) + + Returns: + dict: Serialized FrackturePayload containing compressed data + + Example: + >>> data = b"Hello world" + >>> result = compress(data) + >>> print(result['symbolic']) # 64-char hex fingerprint + >>> print(len(result['entropy'])) # 16 entropy components + """ + result = _global_engine.compress(data, passes, optimize, num_trials) + return result.payload.to_dict() + + +def decompress(payload): + """ + Decompress Frackture payload to vector representation. + + Args: + payload: FrackturePayload (dict or object) to decompress + + Returns: + np.ndarray: 768-length reconstructed vector + + Example: + >>> payload = {'symbolic': '...', 'entropy': [...]} + >>> vector = decompress(payload) + >>> print(len(vector)) # 768 + """ + return _global_engine.decompress(payload) + + +def encrypt(data, key_material: bytes, passes: int = None): + """ + Encrypt data using key-based Frackture compression. + + Args: + data: Input data to encrypt + key_material: Encryption key material (bytes) + passes: Number of symbolic passes (default: 4) + + Returns: + dict: Serialized encrypted FrackturePayload + + Example: + >>> data = b"Secret message" + >>> key = b"my-encryption-key" + >>> encrypted = encrypt(data, key) + >>> print(encrypted['encryption']['mode']) # 'xor' + """ + result = _global_engine.encrypt(data, key_material, passes) + return result.payload.to_dict() + + +def decrypt(payload, key_material: bytes): + """ + Decrypt Frackture payload using key material. + + Args: + payload: Encrypted FrackturePayload (dict or object) + key_material: Encryption key material (bytes) + + Returns: + np.ndarray: 768-length decrypted vector + + Example: + >>> encrypted_payload = {...} # From encrypt() + >>> key = b"my-encryption-key" + >>> vector = decrypt(encrypted_payload, key) + """ + return _global_engine.decrypt(payload, key_material) + + +def fingerprint(data, passes: int = None): + """ + Generate fingerprint for data without full compression. + + Args: + data: Input data to fingerprint + passes: Number of symbolic passes (default: 4) + + Returns: + str: 64-character hexadecimal fingerprint + + Example: + >>> data = b"Test data" + >>> fp = fingerprint(data) + >>> print(len(fp)) # 64 + >>> print(fp[:16]) # First 16 characters + """ + return _global_engine.fingerprint(data, passes) + + +def verify_payload(payload) -> bool: + """ + Verify payload integrity using stored fingerprint. + + Args: + payload: FrackturePayload (dict or object) to verify + + Returns: + bool: True if payload is valid and fingerprint matches + + Example: + >>> payload = {...} # Some payload + >>> is_valid = verify_payload(payload) + >>> if is_valid: + ... print("Payload is valid") + """ + return _global_engine.verify_payload(payload) + + +def get_version() -> str: + """ + Get current Frackture version. + + Returns: + str: Version string + """ + return __version__ + + +def create_engine(version=None): + """ + Create a new FracktureEngine instance. + + Args: + version: Frackture version to use (default: current) + + Returns: + FracktureEngine: New engine instance + + Example: + >>> engine = create_engine() + >>> result = engine.compress("test data") + """ + if version is None: + return FracktureEngine() + return FracktureEngine(version) + + +# Define what gets exported with "from frackture import *" +__all__ = [ + # Core classes + "FracktureEngine", + "FrackturePayload", + "CompressionMetadata", + "EncryptionMetadata", + "CompressionResult", + "FracktureVersion", + "EncryptionMode", + + # Convenience functions + "compress", + "decompress", + "encrypt", + "decrypt", + "fingerprint", + "verify_payload", + "get_version", + "create_engine", + + # Core processing functions + "frackture_preprocess_universal_v2_6", + "symbolic_channel_encode", + "symbolic_channel_decode", + "symbolic_fingerprint_with_key", + "entropy_channel_encode", + "entropy_channel_decode", + "entropy_signature_with_key", +] \ No newline at end of file diff --git a/frackture/__main__.py b/frackture/__main__.py new file mode 100644 index 0000000..d1f9018 --- /dev/null +++ b/frackture/__main__.py @@ -0,0 +1,12 @@ +""" +CLI entry point for Frackture package. + +This module allows the frackture package to be executed as a module: + python -m frackture compress input.txt + python -m frackture fingerprint data.txt +""" + +from .cli import main + +if __name__ == "__main__": + main() \ No newline at end of file diff --git a/frackture/__pycache__/__init__.cpython-312.pyc b/frackture/__pycache__/__init__.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..00a9d0ffc76e89c979162b731fc937cf42f2e6ff GIT binary patch literal 6796 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 literal 0 HcmV?d00001 diff --git a/frackture/__pycache__/engine.cpython-312.pyc b/frackture/__pycache__/engine.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..ae63e9c5a7204cf1d2152d49dfc25bace934b1e6 GIT binary patch literal 14908 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 literal 0 HcmV?d00001 diff --git a/frackture/__pycache__/entropy.cpython-312.pyc b/frackture/__pycache__/entropy.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..e507fb4a76f977a7a937f752ee7971c0bc41ab79 GIT binary patch literal 8553 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 literal 0 HcmV?d00001 diff --git a/frackture/__pycache__/models.cpython-312.pyc b/frackture/__pycache__/models.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..c63292b03e339d3cd0a1b8360241854bbe4966d6 GIT binary patch literal 4962 zcmbVQO>7&-6<%_e|D;I$)1qXpWXlr$L&`rA8pn2=NdAdyOK$9>0b7(U* z^WK};o%!D1@QBZWd%UA`-hWFYiy3W^NFpx^n!x82 zQOc_PoI?1^M96%GBEBFLvx*?9ypR|9oTLe;n(%**pBZ#PbW^##9gL0oz4q6DV;X` z=``$iF^m0RI{nK9nY1fX#h!I(_;XvyGql!&q`&$w^5me^<^+$pTRpq>PrF ztDjQRI=V!mNYJ<_!H$aL0rO|>9U~C=Vw$wqh5MgE6vS_yg2<*^MGii{?NUBNiu71- z092*e?m0*e2}My&m|R}TOD6ldLT2J_62KP+k$}lFqz#D4&CJeRGTBdOKOzxi(vR!F z9-=`>7&B%??uAg((_O;X7iG7ce$BWdxd5#%93G}ZTjAVNta z7O%z$wQCZC9-(jk{2Wt3^;U`XhGlx{|iW*t>>Yzc%|T+Q}jLH z0G>9{F9k)f$jotK-~rc2T;ZZS9&8HRH?0g(`i-B5h7OtqhieMmc8cMDC2RA%kj*xw z8Jt0<-JX|K9!$TUupmhRhP;$lAxWvch%TIy^Rk+wiE2**;DroPRF$qH%5!rPk@DJZ z!ob9qQSx*0-9=(KVS=ifUbUFJqh#fb>46DEDHKgF#0r`LP5-Wy&6t5XIe%9o1p;1c zx`_mtGoPs^H#lF$3qOb>%ytiijx}b9SwL<}1Fl^JGz)->@u;OOpzXD^1$;|Od&}&7 zBJo=^F=@24w`gKgX=!iKMCWK}qT{g(v@!j(v;}m(miCsN?l-%qWhxBc@*d2-EsY%h z-*p!-nzyvNPvoJ96xqittk&P60z;8|?7GFoU8V6UB@a1Bs~26ortl(^RFGc;Qly2M zO2d|&bP~^8G>6cX(UL7@p0QTAqJarx5-6X52T34FA{j?=5(s3f77wp{d_exuE)l!u}M8PY4ja@a$@~NwJ)LfC5)kwZwI~^s1BXe zht3(J$G*M)&Hd`=RekiTad7xaZar5$IH@0;+zPl4wACWGc6dEpjULyd$E(p(dh`^o zmRwI(`^NRYabxoA@08yv)yZq$O2q77!DW%#7}3bw z7`gVy+&FsSd2Z)}`%bN%85qq2BHCcC7xhFR(x$grT$+3vIsw!nF|83}7O>sxWL%w@S?rGAMlor(#a`WX*HZ> zjwrcicNr6C*eSXPgwy{}E5K>_uNy@owQCQ!2LA?Pw>5=h)b%Py;=!(?og&PSnV zdhmO|BTN;B#lVg!&T|Dks$!t{*2ZXev>Hh!-2r(RC#{MkzTySQXf?;P2f*E^HO zg%AF4PQP$-^Cv(3?!u>Ecdres4wSWx>-ylymq+x$cV4xh-TcL!9S_&zf9T%|GLcTB z`#|}q-aTS;Mau_PXN~Rwqj$)N_CN8idp8Cu(ImVby~k~PPdu`3A$AB)ZwLumv+0_H zo2h0YKo6hdf{Bsf!IHD66rh(=NZa#@NG>89vyW9iVPGQ1>jVRtDgpV5+2UL-Z>^09 zcYJxn2(_<_Jo;IMi$YWi4_CM$BLZ|7M#D#zf4mYcA6kXtdZfm6xcud=Z3Z5-F~;3q zbM^q^c8!6@=8+%$6QA2G2)0mQeF45a1HVSAhl1@p!1}KRT)lL2H%d28Q|U%8Qs`K~ zvr0EC=iqW>^XN4S3N@eE-gIU9NKzNGT4~sN^2!`9?71x|1<5Lr;Id>_ZDvRzGTe%V zY+98|k{PbwuHXtp8SQlj-je9-8I#Sak{R7|f0E%&rreWqP-(>j`=U>QqUaC9zR3GX zK14zhzlOaQXs3~fM24S==73fAaRVTi!ziFVSm6eZ z@iUuTe|dgmab0=Eow4x3#b&@d=>Go&B9cN0H&&sqOeTp%-`jG<8dHIN$Xa5%P{P6zidFXI^gE0d@& ziN7%2J8q|=eMQ@0;IZRp9g&sWI}AK(LB<*Qx6|zy0XK7ufFU{qH9G8|0+(Z`#sIMe hIE+xic?UQq5LI3{Wg5GvVnLXRHOe*lbUIw1f6 literal 0 HcmV?d00001 diff --git a/frackture/__pycache__/preprocess.cpython-312.pyc b/frackture/__pycache__/preprocess.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..435275dd4c2873dd9688b1265d589a8e91821db2 GIT binary patch literal 4682 zcmb_gZ)_9E6`%F~@xO$CV+WdpV+CA@kHn#Ajtf4H_6Vc_RrF6F*W;+H#k)@I*lTNc z9TLl_PE|iRy;GCuPKr^H02K)kNQe4~N|nkqQjSn8n{KI!zPflpqP||V^YdM^aYle~3N99ab&8Iavk;U>L zR^sDk9%~Vw@6=e*U}Iy7uBJ6Zj%RfcVUk%B3QlJ8hMd%Mc~ds0axmO!m>9;4F8SP) zsX>)a8YWZ<#>y1bni-FTeM#NS%6b-OlytJ7sq*Uw`n%JbK5CB16I$HNVna5^6jL@d zJfX=7X%Xx4x~iDTtWFJ8(rL$7Ih)fk9Wx@nugE^147)55)|=HW{w;mV5@4!gNmzrm z>2c0+1tN~+;kWXsKpg8uW_`4XOc&$4S)=d)Q)GQ9iBV2nL@BS+VwB3=tVuONi(OJQ z*jUT1Z@HMBX>N|wkFT<&iSaTX{I*Ffr^Rex6j-o@(N2A{Mlw5CJ?(nIdR*Vsdh{<> zttP;1tFNZx1(u+%zjykrRl4d&u&%4GL022I#Hqpaj-R$U{fu(_lzNHvIW^nsX-*$o zWrrhkyTi?>x@}v)gBweIv%&gxV$g|-B4U32ro33>QahQ&PQCGNF&n1&2D@cvHlvDs zol|Jw+{MP7x`9(HibbISXG!G?z%VTpdAnVd3Vvww<|}NTGfNf5;XLEc1}z4 zFsMlkc#xiw<=UW{jGIw;IEzgf1xR9eWDB#wr;EUazK&#qMQhY2(pkm)POptmRA3^l zn5L#{YE7e_iva8p_*!cdQNNa(>~j{>V~U4slx=7pRreMiHSE12&Lggh%Eu|ZQnzIj z)R9I$m$P?(fG(X#*eUT73UCcV8tp&1F66R3u%UO2I3;Ol4bqNH#8ADd9pKq!-x@M1+D)hH=}G!>XQ%^=wVaUU(ux_ZX4 z8LbDBp`@<$K#rDz1JILTSsC=O#4VDWvUb-8V$MLUepF)%PU-uF}y*&!0O}o2xA~@2RV}b>!or8zA{LHcBOfkk0we za^F>at#GBV6zF{zh*kp8#lRuPc8;iBY7RdRv@LYacYPR{8F(t8)(|oLDu4OtZ@mxY z{S|rt?X8RQ!A}E!+V;t|rND{OKvhD4&_ers`^6)dPFy&#xMgoivL|-Tca+;cjFjAD z3H8Po!I#RTmEbGag-Woi#>Zs1w`|xU=dl4;{{On83yI1< zfaR>7MX5r8V;l0e&K$!pOYowc;zh|C9_TLwW@f*-2`(jMOr^<62 z_fMC|2`ifr*ZMcKqbhxm<9e=Zw+HTo?h1F+dq@6q;{J&TKYjN>-@BE_*(xH#50v;r vWxS${uh3?7(Bx-Q9bu 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 str: + """Load data from file.""" + try: + with open(file_path, 'r', encoding='utf-8') as f: + return f.read() + except Exception as e: + print(f"Error loading file {file_path}: {e}", file=sys.stderr) + sys.exit(1) + + +def save_data(data: str, file_path: str) -> None: + """Save data to file.""" + try: + with open(file_path, 'w', encoding='utf-8') as f: + f.write(data) + except Exception as e: + print(f"Error saving file {file_path}: {e}", file=sys.stderr) + sys.exit(1) + + +def compress_command(args): + """Handle compress command.""" + engine = FracktureEngine() + + # Load input data + data = load_data(args.input) + + try: + # Perform compression + result = engine.compress( + data, + passes=args.passes, + optimize=args.optimize, + num_trials=args.trials + ) + + # Output results + if args.output: + save_data(json.dumps(result.payload.to_dict(), indent=2), args.output) + print(f"Compression successful. Output saved to {args.output}") + print(f"Original size: {result.original_size} bytes") + print(f"Compressed size: {result.compressed_size} bytes") + print(f"Compression ratio: {result.compression_ratio:.3f}") + print(f"Reconstruction MSE: {result.mse:.6f}") + else: + print(json.dumps(result.payload.to_dict(), indent=2)) + + except Exception as e: + print(f"Compression failed: {e}", file=sys.stderr) + sys.exit(1) + + +def decompress_command(args): + """Handle decompress command.""" + engine = FracktureEngine() + + # Load payload + try: + with open(args.input, 'r', encoding='utf-8') as f: + payload_dict = json.load(f) + except Exception as e: + print(f"Error loading payload {args.input}: {e}", file=sys.stderr) + sys.exit(1) + + try: + # Perform decompression + vector = engine.decompress(payload_dict) + + # Output results + if args.output: + save_data(str(vector.tolist()), args.output) + print(f"Decompression successful. Vector saved to {args.output}") + else: + print("Decompressed vector (first 10 elements):") + print(vector[:10].tolist()) + print(f"... ({len(vector)} total elements)") + + except Exception as e: + print(f"Decompression failed: {e}", file=sys.stderr) + sys.exit(1) + + +def encrypt_command(args): + """Handle encrypt command.""" + engine = FracktureEngine() + + # Load input data + data = load_data(args.input) + + # Load key material + try: + with open(args.key, 'rb') as f: + key_material = f.read() + except Exception as e: + print(f"Error loading key file {args.key}: {e}", file=sys.stderr) + sys.exit(1) + + try: + # Perform encryption + result = engine.encrypt(data, key_material, passes=args.passes) + + # Output results + if args.output: + save_data(json.dumps(result.payload.to_dict(), indent=2), args.output) + print(f"Encryption successful. Output saved to {args.output}") + print(f"Original size: {result.original_size} bytes") + print(f"Encrypted size: {result.compressed_size} bytes") + print(f"Compression ratio: {result.compression_ratio:.3f}") + else: + print(json.dumps(result.payload.to_dict(), indent=2)) + + except Exception as e: + print(f"Encryption failed: {e}", file=sys.stderr) + sys.exit(1) + + +def decrypt_command(args): + """Handle decrypt command.""" + engine = FracktureEngine() + + # Load payload + try: + with open(args.input, 'r', encoding='utf-8') as f: + payload_dict = json.load(f) + except Exception as e: + print(f"Error loading payload {args.input}: {e}", file=sys.stderr) + sys.exit(1) + + # Load key material + try: + with open(args.key, 'rb') as f: + key_material = f.read() + except Exception as e: + print(f"Error loading key file {args.key}: {e}", file=sys.stderr) + sys.exit(1) + + try: + # Perform decryption + vector = engine.decrypt(payload_dict, key_material) + + # Output results + if args.output: + save_data(str(vector.tolist()), args.output) + print(f"Decryption successful. Vector saved to {args.output}") + else: + print("Decrypted vector (first 10 elements):") + print(vector[:10].tolist()) + print(f"... ({len(vector)} total elements)") + + except Exception as e: + print(f"Decryption failed: {e}", file=sys.stderr) + sys.exit(1) + + +def fingerprint_command(args): + """Handle fingerprint command.""" + engine = FracktureEngine() + + # Load input data + data = load_data(args.input) + + try: + # Generate fingerprint + fingerprint = engine.fingerprint(data, passes=args.passes) + + # Output results + if args.output: + save_data(fingerprint, args.output) + print(f"Fingerprint generated successfully. Output saved to {args.output}") + else: + print(fingerprint) + + except Exception as e: + print(f"Fingerprint generation failed: {e}", file=sys.stderr) + sys.exit(1) + + +def verify_command(args): + """Handle verify command.""" + engine = FracktureEngine() + + # Load payload + try: + with open(args.input, 'r', encoding='utf-8') as f: + payload_dict = json.load(f) + except Exception as e: + print(f"Error loading payload {args.input}: {e}", file=sys.stderr) + sys.exit(1) + + try: + # Verify payload + is_valid = engine.verify_payload(payload_dict) + + if is_valid: + print("✓ Payload verification successful - payload is valid") + else: + print("✗ Payload verification failed - payload is invalid or corrupted") + sys.exit(1) + + except Exception as e: + print(f"Verification failed: {e}", file=sys.stderr) + sys.exit(1) + + +def create_parser() -> argparse.ArgumentParser: + """Create and configure the argument parser.""" + parser = argparse.ArgumentParser( + description="Frackture - Symbolic compression and fingerprinting engine", + prog="frackture" + ) + + subparsers = parser.add_subparsers(dest="command", help="Available commands") + + # Compress command + compress_parser = subparsers.add_parser("compress", help="Compress data") + compress_parser.add_argument("input", help="Input file path") + compress_parser.add_argument("-o", "--output", help="Output file path") + compress_parser.add_argument("-p", "--passes", type=int, help="Number of symbolic passes") + compress_parser.add_argument("--optimize", action="store_true", help="Use optimization") + compress_parser.add_argument("--trials", type=int, default=5, help="Number of optimization trials") + compress_parser.set_defaults(func=compress_command) + + # Decompress command + decompress_parser = subparsers.add_parser("decompress", help="Decompress data") + decompress_parser.add_argument("input", help="Input payload file path") + decompress_parser.add_argument("-o", "--output", help="Output file path") + decompress_parser.set_defaults(func=decompress_command) + + # Encrypt command + encrypt_parser = subparsers.add_parser("encrypt", help="Encrypt data with key") + encrypt_parser.add_argument("input", help="Input file path") + encrypt_parser.add_argument("key", help="Key file path") + encrypt_parser.add_argument("-o", "--output", help="Output file path") + encrypt_parser.add_argument("-p", "--passes", type=int, help="Number of symbolic passes") + encrypt_parser.set_defaults(func=encrypt_command) + + # Decrypt command + decrypt_parser = subparsers.add_parser("decrypt", help="Decrypt data with key") + decrypt_parser.add_argument("input", help="Input payload file path") + decrypt_parser.add_argument("key", help="Key file path") + decrypt_parser.add_argument("-o", "--output", help="Output file path") + decrypt_parser.set_defaults(func=decrypt_command) + + # Fingerprint command + fingerprint_parser = subparsers.add_parser("fingerprint", help="Generate fingerprint") + fingerprint_parser.add_argument("input", help="Input file path") + fingerprint_parser.add_argument("-o", "--output", help="Output file path") + fingerprint_parser.add_argument("-p", "--passes", type=int, help="Number of symbolic passes") + fingerprint_parser.set_defaults(func=fingerprint_command) + + # Verify command + verify_parser = subparsers.add_parser("verify", help="Verify payload integrity") + verify_parser.add_argument("input", help="Input payload file path") + verify_parser.set_defaults(func=verify_command) + + return parser + + +def main(): + """Main CLI entry point.""" + parser = create_parser() + args = parser.parse_args() + + if not args.command: + parser.print_help() + sys.exit(1) + + # Execute the appropriate command + args.func(args) + + +if __name__ == "__main__": + main() \ No newline at end of file diff --git a/frackture/engine.py b/frackture/engine.py new file mode 100644 index 0000000..f8661aa --- /dev/null +++ b/frackture/engine.py @@ -0,0 +1,412 @@ +""" +Core Frackture engine that unifies all channels and provides the main API. + +This module contains the FracktureEngine class which orchestrates the +preprocessing, symbolic, and entropy channels to provide a unified +compression and fingerprinting interface. +""" + +import time +import hashlib +from typing import Union, Optional, Dict, Any + +import numpy as np + +from .models import ( + FrackturePayload, + CompressionMetadata, + EncryptionMetadata, + CompressionResult, + FracktureVersion, + EncryptionMode +) +from .preprocess import frackture_preprocess_universal_v2_6, validate_preprocessed_vector +from .symbolic import ( + symbolic_channel_encode, + symbolic_channel_decode, + symbolic_fingerprint_with_key, + validate_symbolic_hash +) +from .entropy import ( + entropy_channel_encode, + entropy_channel_decode, + entropy_signature_with_key, + validate_entropy_signature +) + + +class FracktureEngine: + """ + Unified Frackture compression and fingerprinting engine. + + This engine orchestrates the preprocessing, symbolic, and entropy channels + to provide a clean API for compression, decompression, encryption, + decryption, and fingerprinting operations. + """ + + def __init__(self, version: FracktureVersion = FracktureVersion.V3_3): + """ + Initialize the Frackture engine. + + Args: + version: Frackture version to use (default: V3_3) + """ + self.version = version + self.default_passes = 4 + self.target_length = 768 + + def _create_metadata(self, passes: Optional[int] = None) -> CompressionMetadata: + """Create compression metadata with timestamp.""" + return CompressionMetadata( + version=self.version, + passes=passes or self.default_passes, + target_length=self.target_length, + created_at=str(int(time.time())) + ) + + def _create_encryption_metadata( + self, + key_material: Optional[bytes] = None, + mode: EncryptionMode = EncryptionMode.NONE + ) -> EncryptionMetadata: + """Create encryption metadata.""" + return EncryptionMetadata( + mode=mode, + key_material=key_material, + salt=key_material[:8] if key_material else None # Use first 8 bytes as salt + ) + + def _generate_fingerprint(self, payload_dict: Dict) -> str: + """Generate fingerprint for payload validation.""" + # Create deterministic string representation + content = f"{payload_dict['symbolic']}{payload_dict['entropy']}{payload_dict['metadata']['version']}" + return hashlib.sha256(content.encode()).hexdigest()[:16] + + def compress( + self, + data: Union[str, bytes, dict, list, np.ndarray, Any], + passes: Optional[int] = None, + optimize: bool = False, + num_trials: int = 5 + ) -> CompressionResult: + """ + Compress input data using Frackture's dual-channel approach. + + Args: + data: Input data of any supported type + passes: Number of symbolic passes (default: engine default) + optimize: Whether to use self-optimization (default: False) + num_trials: Number of optimization trials (default: 5) + + Returns: + CompressionResult: Complete compression result with metadata + + Raises: + ValueError: If preprocessing fails + Exception: If compression fails + """ + try: + # Preprocess input + processed = frackture_preprocess_universal_v2_6(data) + + if not validate_preprocessed_vector(processed): + raise ValueError("Preprocessing failed - invalid vector produced") + + original_size = len(str(data).encode('utf-8')) + + # Use optimization if requested + if optimize: + payload, mse = self._optimize_compression(processed, num_trials, passes) + else: + # Standard compression + actual_passes = passes or self.default_passes + + # Encode through both channels + symbolic = symbolic_channel_encode(processed, actual_passes) + entropy = entropy_channel_encode(processed) + + # Create payload + metadata = self._create_metadata(actual_passes) + encryption = self._create_encryption_metadata() + + payload = FrackturePayload( + symbolic=symbolic, + entropy=entropy, + metadata=metadata, + encryption=encryption + ) + + # Generate fingerprint + payload.fingerprint = self._generate_fingerprint(payload.to_dict()) + + # Calculate MSE + reconstructed = self.decompress(payload) + mse = float(np.mean((processed - reconstructed) ** 2)) + + # Calculate compression statistics + payload_dict = payload.to_dict() + import json + compressed_size = len(json.dumps(payload_dict).encode('utf-8')) + compression_ratio = compressed_size / original_size if original_size > 0 else 0.0 + + return CompressionResult( + payload=payload, + original_size=original_size, + compressed_size=compressed_size, + compression_ratio=compression_ratio, + mse=mse + ) + + except Exception as e: + raise Exception(f"Compression failed: {e}") + + def _optimize_compression( + self, + processed: np.ndarray, + num_trials: int, + base_passes: Optional[int] + ) -> tuple: + """Perform optimization to find best compression parameters.""" + best_payload = None + best_mse = float("inf") + + base_passes_val = base_passes or self.default_passes + + for trial in range(num_trials): + # Try different pass counts + passes_to_try = base_passes_val + trial + + symbolic = symbolic_channel_encode(processed, passes_to_try) + entropy = entropy_channel_encode(processed) + + metadata = self._create_metadata(passes_to_try) + metadata.optimization_trials = trial + 1 + + encryption = self._create_encryption_metadata() + + payload = FrackturePayload( + symbolic=symbolic, + entropy=entropy, + metadata=metadata, + encryption=encryption + ) + + payload.fingerprint = self._generate_fingerprint(payload.to_dict()) + + # Test reconstruction quality + reconstructed = self.decompress(payload) + mse = float(np.mean((processed - reconstructed) ** 2)) + + if mse < best_mse: + best_mse = mse + best_payload = payload + + return best_payload, best_mse + + def decompress(self, payload: Union[FrackturePayload, Dict]) -> np.ndarray: + """ + Decompress Frackture payload back to vector representation. + + Args: + payload: FrackturePayload or dictionary representation + + Returns: + np.ndarray: 768-length reconstructed vector + + Raises: + ValueError: If payload format is invalid + Exception: If decompression fails + """ + try: + # Convert dict to payload if needed + if isinstance(payload, dict): + payload = FrackturePayload.from_dict(payload) + + # Validate symbolic hash + if not validate_symbolic_hash(payload.symbolic): + raise ValueError("Invalid symbolic hash in payload") + + # Validate entropy signature + if not validate_entropy_signature(payload.entropy): + raise ValueError("Invalid entropy signature in payload") + + # Decode through both channels + symbolic_part = symbolic_channel_decode(payload.symbolic) + entropy_part = entropy_channel_decode(payload.entropy) + + # Merge reconstructed parts + merged = (np.array(entropy_part) + np.array(symbolic_part)) / 2 + + return merged.astype(np.float32) + + except Exception as e: + raise Exception(f"Decompression failed: {e}") + + def encrypt( + self, + data: Union[str, bytes, dict, list, np.ndarray, Any], + key_material: bytes, + passes: Optional[int] = None + ) -> CompressionResult: + """ + Encrypt data using key-based Frackture compression. + + Args: + data: Input data to encrypt + key_material: Encryption key material + passes: Number of symbolic passes + + Returns: + CompressionResult: Encrypted compression result + + Raises: + ValueError: If key material is invalid + Exception: If encryption fails + """ + if not key_material or len(key_material) == 0: + raise ValueError("Key material is required for encryption") + + try: + # Preprocess input + processed = frackture_preprocess_universal_v2_6(data) + + if not validate_preprocessed_vector(processed): + raise ValueError("Preprocessing failed - invalid vector produced") + + # Create encrypted payload + actual_passes = passes or self.default_passes + + symbolic = symbolic_fingerprint_with_key(processed, key_material, actual_passes) + entropy = entropy_signature_with_key(processed, key_material) + + metadata = self._create_metadata(actual_passes) + encryption = self._create_encryption_metadata(key_material, EncryptionMode.XOR) + + payload = FrackturePayload( + symbolic=symbolic, + entropy=entropy, + metadata=metadata, + encryption=encryption + ) + + payload.fingerprint = self._generate_fingerprint(payload.to_dict()) + + # Calculate statistics + original_size = len(str(data).encode('utf-8')) + import json + compressed_size = len(json.dumps(payload.to_dict()).encode('utf-8')) + compression_ratio = compressed_size / original_size if original_size > 0 else 0.0 + + # Calculate MSE for encrypted version + reconstructed = self.decrypt(payload, key_material) + mse = float(np.mean((processed - reconstructed) ** 2)) + + return CompressionResult( + payload=payload, + original_size=original_size, + compressed_size=compressed_size, + compression_ratio=compression_ratio, + mse=mse + ) + + except Exception as e: + raise Exception(f"Encryption failed: {e}") + + def decrypt(self, payload: Union[FrackturePayload, Dict], key_material: bytes) -> np.ndarray: + """ + Decrypt Frackture payload using key material. + + Args: + payload: Encrypted FrackturePayload + key_material: Encryption key material + + Returns: + np.ndarray: 768-length decrypted vector + + Raises: + ValueError: If payload or key material is invalid + Exception: If decryption fails + """ + if not key_material or len(key_material) == 0: + raise ValueError("Key material is required for decryption") + + try: + # Convert dict to payload if needed + if isinstance(payload, dict): + payload = FrackturePayload.from_dict(payload) + + # Verify encryption mode + if payload.encryption.mode != EncryptionMode.XOR: + raise ValueError("Payload is not encrypted with XOR mode") + + # Decrypt through both channels (reconstruct with key) + symbolic_part = symbolic_channel_decode(payload.symbolic) + entropy_part = entropy_channel_decode(payload.entropy) + + # Merge decrypted parts + merged = (np.array(entropy_part) + np.array(symbolic_part)) / 2 + + return merged.astype(np.float32) + + except Exception as e: + raise Exception(f"Decryption failed: {e}") + + def fingerprint( + self, + data: Union[str, bytes, dict, list, np.ndarray, Any], + passes: Optional[int] = None + ) -> str: + """ + Generate fingerprint for data without full compression. + + Args: + data: Input data to fingerprint + passes: Number of symbolic passes + + Returns: + str: 64-character hexadecimal fingerprint + + Raises: + Exception: If fingerprinting fails + """ + try: + # Preprocess input + processed = frackture_preprocess_universal_v2_6(data) + + if not validate_preprocessed_vector(processed): + raise ValueError("Preprocessing failed - invalid vector produced") + + # Generate symbolic fingerprint only + actual_passes = passes or self.default_passes + return symbolic_channel_encode(processed, actual_passes) + + except Exception as e: + raise Exception(f"Fingerprinting failed: {e}") + + def verify_payload(self, payload: Union[FrackturePayload, Dict]) -> bool: + """ + Verify payload integrity using stored fingerprint. + + Args: + payload: FrackturePayload to verify + + Returns: + bool: True if payload is valid and fingerprint matches + """ + try: + # Convert dict to payload if needed + if isinstance(payload, dict): + payload = FrackturePayload.from_dict(payload) + + # Check if fingerprint exists + if not payload.fingerprint: + return False + + # Recalculate fingerprint + current_fingerprint = self._generate_fingerprint(payload.to_dict()) + + # Compare fingerprints + return payload.fingerprint == current_fingerprint + + except Exception: + return False \ No newline at end of file diff --git a/frackture/entropy.py b/frackture/entropy.py new file mode 100644 index 0000000..4b0ae73 --- /dev/null +++ b/frackture/entropy.py @@ -0,0 +1,245 @@ +""" +Entropy channel module for Frackture. + +This module implements the entropy channel using FFT analysis and PCA +to create frequency-domain signatures that complement the symbolic channel. +""" + +import numpy as np +from scipy.fft import fft +from sklearn.decomposition import PCA +from typing import List, Tuple + + +def entropy_channel_encode(input_vector: np.ndarray) -> List[float]: + """ + Encode input vector through entropy channel using FFT + PCA. + + The entropy channel captures frequency-domain characteristics: + 1. Apply FFT to get frequency spectrum + 2. Use PCA for dimensionality reduction + 3. Return compact 16-component signature + + Args: + input_vector: 768-length normalized vector + + Returns: + List[float]: 16-component entropy signature + + Raises: + ValueError: If input vector is not 768 elements + """ + if len(input_vector) != 768: + raise ValueError(f"Input vector must be 768 elements, got {len(input_vector)}") + + # Apply FFT to get frequency spectrum + fft_vector = np.abs(fft(input_vector)) + + # For single samples, use statistical summarization instead of PCA + # This gives us 16 meaningful components without needing multiple samples + reduced = [] + + # Split FFT spectrum into 16 segments and compute statistics + segment_size = len(fft_vector) // 16 + if segment_size == 0: + # If vector is too small, pad with zeros + reduced = [0.0] * 16 + else: + for i in range(16): + start_idx = i * segment_size + end_idx = min(start_idx + segment_size, len(fft_vector)) + + segment = fft_vector[start_idx:end_idx] + if len(segment) > 0: + # Use mean and std of segment as features (convert to Python float) + mean_val = float(np.mean(segment)) + std_val = float(np.std(segment) / 2.0) + reduced.extend([mean_val, std_val]) # 2 features per segment + else: + reduced.extend([0.0, 0.0]) + + # Take only first 16 components + reduced = reduced[:16] + + # If we got fewer than 16, pad with zeros + while len(reduced) < 16: + reduced.append(0.0) + + return reduced + + +def entropy_channel_decode(entropy_data: List[float]) -> np.ndarray: + """ + Decode entropy signature back to approximate vector representation. + + This attempts reconstruction by: + 1. Expanding 16 components to 768 via tiling + 2. Normalizing to [0, 1] range + + Args: + entropy_data: 16-component entropy signature + + Returns: + np.ndarray: 768-length normalized vector (approximation) + + Raises: + ValueError: If entropy data doesn't have 16 components + """ + if len(entropy_data) != 16: + raise ValueError(f"Entropy data must have 16 components, got {len(entropy_data)}") + + try: + # Convert to numpy array + ent = np.array(entropy_data) + + # Expand to 768 elements by tiling + expanded = np.tile(ent, 48)[:768] + + # Normalize to [0, 1] range + min_val = np.min(expanded) + max_val = np.max(expanded) + range_val = max_val - min_val + 1e-8 + + normed = (expanded - min_val) / range_val + + return normed.astype(np.float32) + + except Exception as e: + raise ValueError(f"Failed to decode entropy data: {e}") + + +def compute_frequency_spectrum(input_vector: np.ndarray) -> Tuple[np.ndarray, np.ndarray]: + """ + Compute full frequency spectrum for analysis. + + Args: + input_vector: 768-length normalized vector + + Returns: + Tuple[np.ndarray, np.ndarray]: (frequencies, magnitudes) + + Raises: + ValueError: If input vector is not 768 elements + """ + if len(input_vector) != 768: + raise ValueError(f"Input vector must be 768 elements, got {len(input_vector)}") + + # Apply FFT + fft_result = fft(input_vector) + + # Get magnitude spectrum + magnitudes = np.abs(fft_result) + + # Generate frequency bins + frequencies = np.fft.fftfreq(len(input_vector)) + + return frequencies, magnitudes + + +def apply_key_based_spectral_masking( + frequencies: np.ndarray, + key_material: bytes +) -> np.ndarray: + """ + Apply key-based masking to frequency spectrum for encryption. + + Args: + frequencies: Input frequency magnitudes + key_material: Encryption key material + + Returns: + np.ndarray: Masked frequency magnitudes + """ + if not key_material: + return frequencies + + # Generate mask from key material + key_mask = np.frombuffer( + (key_material * (len(frequencies) // len(key_material) + 1))[:len(frequencies)], + dtype=np.uint8 + ).astype(np.float32) + + # Ensure uint8 range for masking operation + # Use bitwise AND with 0xFF to ensure we stay in uint8 range + masked = ((frequencies.astype(np.uint16) ^ key_mask.astype(np.uint16)) & 0xFF).astype(np.uint8) + + # Normalize back to reasonable range + masked = masked / 255.0 + + return masked + + +def entropy_signature_with_key( + input_vector: np.ndarray, + key_material: bytes +) -> List[float]: + """ + Generate entropy signature with key-based masking for encryption. + + Args: + input_vector: 768-length normalized vector + key_material: Encryption key material + + Returns: + List[float]: 16-component encrypted entropy signature + """ + if len(input_vector) != 768: + raise ValueError(f"Input vector must be 768 elements, got {len(input_vector)}") + + # Apply FFT + fft_vector = np.abs(fft(input_vector)) + + # Apply key-based masking to spectrum + if key_material: + fft_vector = apply_key_based_spectral_masking(fft_vector, key_material) + + # For single samples, use statistical summarization instead of PCA + # This gives us 16 meaningful components without needing multiple samples + reduced = [] + + # Split FFT spectrum into 16 segments and compute statistics + segment_size = len(fft_vector) // 16 + if segment_size == 0: + # If vector is too small, pad with zeros + reduced = [0.0] * 16 + else: + for i in range(16): + start_idx = i * segment_size + end_idx = min(start_idx + segment_size, len(fft_vector)) + + segment = fft_vector[start_idx:end_idx] + if len(segment) > 0: + # Use mean and std of segment as features (convert to Python float) + mean_val = float(np.mean(segment)) + std_val = float(np.std(segment) / 2.0) + reduced.extend([mean_val, std_val]) # 2 features per segment + else: + reduced.extend([0.0, 0.0]) + + # Take only first 16 components + reduced = reduced[:16] + + # If we got fewer than 16, pad with zeros + while len(reduced) < 16: + reduced.append(0.0) + + return reduced + + +def validate_entropy_signature(entropy_data: List[float]) -> bool: + """ + Validate entropy signature format. + + Args: + entropy_data: Signature to validate + + Returns: + bool: True if valid 16-component float list + """ + try: + return ( + len(entropy_data) == 16 and + all(isinstance(x, (int, float, np.number)) and not np.isnan(x) for x in entropy_data) + ) + except Exception: + return False \ No newline at end of file diff --git a/frackture/models.py b/frackture/models.py new file mode 100644 index 0000000..6aeea56 --- /dev/null +++ b/frackture/models.py @@ -0,0 +1,113 @@ +""" +Structured data models for Frackture payloads and metadata. +""" + +from dataclasses import dataclass +from typing import Dict, List, Optional, Union +from enum import Enum + + +class FracktureVersion(Enum): + """Supported Frackture versions for compatibility.""" + V3_3 = "3.3" + + +class EncryptionMode(Enum): + """Supported encryption modes.""" + NONE = "none" + XOR = "xor" + + +@dataclass +class CompressionMetadata: + """Metadata about compression parameters.""" + version: FracktureVersion = FracktureVersion.V3_3 + passes: int = 4 + target_length: int = 768 + optimization_trials: int = 0 + created_at: Optional[str] = None + + +@dataclass +class EncryptionMetadata: + """Metadata about encryption parameters.""" + mode: EncryptionMode = EncryptionMode.NONE + key_material: Optional[bytes] = None + key_id: Optional[str] = None + salt: Optional[bytes] = None + + +@dataclass +class FrackturePayload: + """ + Complete Frackture payload with all metadata. + + This structured format ensures determinism and compatibility across + different versions and configurations. + """ + # Core data + symbolic: str + entropy: List[float] + + # Metadata + metadata: CompressionMetadata + encryption: EncryptionMetadata + + # Validation + fingerprint: Optional[str] = None + + def to_dict(self) -> Dict: + """Convert payload to dictionary for serialization.""" + return { + "symbolic": self.symbolic, + "entropy": self.entropy, + "metadata": { + "version": self.metadata.version.value, + "passes": self.metadata.passes, + "target_length": self.metadata.target_length, + "optimization_trials": self.metadata.optimization_trials, + "created_at": self.metadata.created_at, + }, + "encryption": { + "mode": self.encryption.mode.value, + "key_id": self.encryption.key_id, + "salt": self.encryption.salt.hex() if self.encryption.salt else None, + }, + "fingerprint": self.fingerprint, + } + + @classmethod + def from_dict(cls, data: Dict) -> "FrackturePayload": + """Create payload from dictionary (deserialization).""" + metadata = CompressionMetadata( + version=FracktureVersion(data["metadata"]["version"]), + passes=data["metadata"]["passes"], + target_length=data["metadata"]["target_length"], + optimization_trials=data["metadata"]["optimization_trials"], + created_at=data["metadata"]["created_at"], + ) + + encryption = EncryptionMetadata( + mode=EncryptionMode(data["encryption"]["mode"]), + key_id=data["encryption"]["key_id"], + salt=bytes.fromhex(data["encryption"]["salt"]) if data["encryption"]["salt"] else None, + ) + + return cls( + symbolic=data["symbolic"], + entropy=data["entropy"], + metadata=metadata, + encryption=encryption, + fingerprint=data.get("fingerprint"), + ) + + +@dataclass +class CompressionResult: + """Result of a compression operation.""" + payload: FrackturePayload + original_size: int + compressed_size: int + compression_ratio: float + mse: Optional[float] = None + optimization_improvement: Optional[float] = None \ No newline at end of file diff --git a/frackture/preprocess.py b/frackture/preprocess.py new file mode 100644 index 0000000..58d3b20 --- /dev/null +++ b/frackture/preprocess.py @@ -0,0 +1,108 @@ +""" +Universal preprocessing module for Frackture. + +This module handles converting various input types (strings, bytes, lists, arrays, etc.) +into normalized 768-length vectors that serve as the foundation for all Frackture operations. +""" + +import numpy as np +from typing import Union, Any + + +def frackture_preprocess_universal_v2_6(data: Union[str, bytes, dict, list, np.ndarray, Any]) -> np.ndarray: + """ + Convert any input data into a normalized 768-length vector. + + This universal preprocessing function handles multiple input types: + - str: Converted to UTF-8 bytes + - bytes: Used directly + - dict: Sorted and converted to string, then UTF-8 bytes + - list: Converted to float32 array and flattened + - np.ndarray: Used directly and flattened + - any other type: Converted to string, then UTF-8 bytes + + Args: + data: Input data of any supported type + + Returns: + np.ndarray: Normalized 768-length float32 vector + + Raises: + Exception: Returns zero vector if preprocessing fails + """ + try: + if isinstance(data, str): + # String input: encode to UTF-8 bytes + vec = np.frombuffer(data.encode("utf-8"), dtype=np.uint8) + elif isinstance(data, dict): + # Dictionary input: sort items, convert to string, encode + flat = str(sorted(data.items())) + vec = np.frombuffer(flat.encode("utf-8"), dtype=np.uint8) + elif isinstance(data, bytes): + # Bytes input: use directly + vec = np.frombuffer(data, dtype=np.uint8) + elif isinstance(data, list): + # List input: convert to float32 array and flatten + vec = np.array(data, dtype=np.float32).flatten() + elif isinstance(data, np.ndarray): + # NumPy array: flatten (preserve dtype) + vec = data.flatten() + else: + # Any other type: convert to string, then UTF-8 bytes + vec = np.frombuffer(str(data).encode("utf-8"), dtype=np.uint8) + + # Normalize to float32 + normed = vec.astype(np.float32) + + # Normalize to [0, 1] range with small epsilon to avoid division by zero + min_val = np.min(normed) + max_val = np.max(normed) + range_val = max_val - min_val + 1e-8 + + normed = (normed - min_val) / range_val + + # Pad or truncate to exactly 768 elements using wrap mode + if len(normed) < 768: + # Pad with wrapped values + padded = np.pad(normed, (0, 768 - len(normed)), mode='wrap') + else: + # Truncate if too long + padded = normed[:768] + + return padded + + except Exception as e: + # Return zero vector on any preprocessing error + return np.zeros(768, dtype=np.float32) + + +def preprocess_batch(data_list: list) -> np.ndarray: + """ + Preprocess a batch of data items. + + Args: + data_list: List of data items to preprocess + + Returns: + np.ndarray: Stack of preprocessed vectors (batch_size, 768) + """ + return np.stack([frackture_preprocess_universal_v2_6(item) for item in data_list]) + + +def validate_preprocessed_vector(vector: np.ndarray) -> bool: + """ + Validate that a vector is properly preprocessed. + + Args: + vector: Vector to validate + + Returns: + bool: True if vector is valid 768-length float32 array + """ + return ( + isinstance(vector, np.ndarray) and + vector.dtype == np.float32 and + len(vector) == 768 and + np.all(vector >= 0.0) and + np.all(vector <= 1.0) + ) \ No newline at end of file diff --git a/frackture/symbolic.py b/frackture/symbolic.py new file mode 100644 index 0000000..22def79 --- /dev/null +++ b/frackture/symbolic.py @@ -0,0 +1,207 @@ +""" +Symbolic fingerprinting module for Frackture. + +This module implements the symbolic channel of Frackture, providing +identity-preserving fingerprint generation and reconstruction. +""" + +import numpy as np +from typing import Tuple, List + + +def frackture_symbolic_fingerprint_f_infinity( + input_vector: np.ndarray, + passes: int = 4 +) -> str: + """ + Generate symbolic fingerprint using recursive XOR/masking operations. + + This function creates an identity-preserving hash by: + 1. Converting input to 8-bit values + 2. Applying progressive XOR masks and rotations + 3. Chunking and folding operations for compression + 4. Multiple passes for enhanced entropy + + Args: + input_vector: 768-length normalized vector + passes: Number of recursive passes (default: 4) + + Returns: + str: 64-character hexadecimal fingerprint (32 chunks of 2 hex chars each) + + Raises: + ValueError: If input vector is not 768 elements + """ + if len(input_vector) != 768: + raise ValueError(f"Input vector must be 768 elements, got {len(input_vector)}") + + # Convert to 8-bit representation + bits = (input_vector * 255).astype(np.uint8) + + # Generate progressive mask based on index + mask = np.array([ + (i**2 + i*3 + 1) % 256 + for i in range(len(bits)) + ], dtype=np.uint8) + + # Apply recursive passes + for p in range(passes): + # Rotate and XOR with mask + rotated = np.roll(bits ^ mask, p * 17) + + # Entropy mixing with pass-dependent scaling (ensure uint8 range) + scaling = (p + 1) ** 2 + entropy_mixed = (rotated.astype(np.uint16) * scaling) % 256 + + # Chunk into 32 segments and fold with XOR reduction + chunks = np.array_split(entropy_mixed, 32) + folded = [np.bitwise_xor.reduce(chunk) for chunk in chunks] + + # Create hexadecimal fingerprint + fingerprint = ''.join(f"{x:02x}" for x in folded) + + # Feed forward for next iteration (ensure uint8 range) + fold_val = folded[p % len(folded)] + bits = (entropy_mixed.astype(np.uint16) + fold_val) % 256 + + return fingerprint + + +def symbolic_channel_encode(input_vector: np.ndarray, passes: int = 4) -> str: + """ + Encode input vector through symbolic channel. + + Args: + input_vector: 768-length normalized vector + passes: Number of fingerprint passes + + Returns: + str: Symbolic fingerprint + """ + return frackture_symbolic_fingerprint_f_infinity(input_vector, passes) + + +def symbolic_channel_decode(symbolic_hash: str) -> np.ndarray: + """ + Decode symbolic hash back to approximate vector representation. + + Note: This is not a true inverse operation - it's a best-effort + reconstruction that preserves some structural properties. + + Args: + symbolic_hash: 64-character hexadecimal fingerprint + + Returns: + np.ndarray: 768-length normalized vector (approximation) + + Raises: + ValueError: If symbolic hash is not valid hex format + """ + if len(symbolic_hash) != 64: + raise ValueError(f"Symbolic hash must be 64 characters, got {len(symbolic_hash)}") + + try: + # Convert hex pairs back to [0, 1] range values + decoded_values = [ + int(symbolic_hash[i:i+2], 16) / 255.0 + for i in range(0, len(symbolic_hash), 2) + ] + + # Expand to 768 elements by tiling + repeated = (decoded_values * (768 // len(decoded_values) + 1))[:768] + + return np.array(repeated, dtype=np.float32) + + except ValueError as e: + raise ValueError(f"Invalid symbolic hash format: {e}") + + +def apply_key_based_masking(bits: np.ndarray, key_material: bytes) -> np.ndarray: + """ + Apply key-based masking to symbolic channel for encryption. + + Args: + bits: Input bit array (uint8) + key_material: Encryption key material + + Returns: + np.ndarray: Masked bit array + """ + if not key_material: + return bits + + # Generate mask from key material + key_mask = np.frombuffer( + (key_material * (len(bits) // len(key_material) + 1))[:len(bits)], + dtype=np.uint8 + ) + + # Ensure uint8 range for masking operation + # Use bitwise AND with 0xFF to ensure we stay in uint8 range + masked = (bits.astype(np.uint16) ^ key_mask.astype(np.uint16)) & 0xFF + return masked.astype(np.uint8) + + +def symbolic_fingerprint_with_key( + input_vector: np.ndarray, + key_material: bytes, + passes: int = 4 +) -> str: + """ + Generate symbolic fingerprint with key-based masking for encryption. + + Args: + input_vector: 768-length normalized vector + key_material: Encryption key material + passes: Number of fingerprint passes + + Returns: + str: Encrypted symbolic fingerprint + """ + if len(input_vector) != 768: + raise ValueError(f"Input vector must be 768 elements, got {len(input_vector)}") + + # Convert to 8-bit representation with masking + bits = (input_vector * 255).astype(np.uint8) + bits = apply_key_based_masking(bits, key_material) + + # Generate mask and apply recursive passes (simplified for encryption) + mask = np.array([ + (i**2 + i*3 + 1) % 256 + for i in range(len(bits)) + ], dtype=np.uint8) + + for p in range(passes): + rotated = np.roll(bits ^ mask, p * 17) + # Entropy mixing with pass-dependent scaling (ensure uint8 range) + scaling = (p + 1) ** 2 + entropy_mixed = (rotated.astype(np.uint16) * scaling) % 256 + + chunks = np.array_split(entropy_mixed, 32) + folded = [np.bitwise_xor.reduce(chunk) for chunk in chunks] + + fingerprint = ''.join(f"{x:02x}" for x in folded) + # Feed forward for next iteration (ensure uint8 range) + fold_val = folded[p % len(folded)] + bits = (entropy_mixed.astype(np.uint16) + fold_val) % 256 + + return fingerprint + + +def validate_symbolic_hash(symbolic_hash: str) -> bool: + """ + Validate symbolic hash format. + + Args: + symbolic_hash: Hash string to validate + + Returns: + bool: True if valid 64-character hex string + """ + try: + return ( + len(symbolic_hash) == 64 and + all(c in '0123456789abcdef' for c in symbolic_hash.lower()) + ) + except Exception: + return False \ No newline at end of file diff --git a/key.txt b/key.txt new file mode 100644 index 0000000..8532974 --- /dev/null +++ b/key.txt @@ -0,0 +1 @@ +my-secret-key diff --git a/secret_input.txt b/secret_input.txt new file mode 100644 index 0000000..69cd329 --- /dev/null +++ b/secret_input.txt @@ -0,0 +1 @@ +secret data diff --git a/test_input.txt b/test_input.txt new file mode 100644 index 0000000..5b9e0c3 --- /dev/null +++ b/test_input.txt @@ -0,0 +1 @@ +Hello world test