exonware-xwsystem 0.0.1.411__py3-none-any.whl → 0.1.0.3__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- exonware/__init__.py +2 -1
- exonware/conf.py +2 -2
- exonware/xwsystem/__init__.py +115 -43
- exonware/xwsystem/base.py +30 -0
- exonware/xwsystem/caching/__init__.py +39 -13
- exonware/xwsystem/caching/base.py +24 -6
- exonware/xwsystem/caching/bloom_cache.py +2 -2
- exonware/xwsystem/caching/cache_manager.py +2 -1
- exonware/xwsystem/caching/conditional.py +2 -2
- exonware/xwsystem/caching/contracts.py +85 -139
- exonware/xwsystem/caching/decorators.py +6 -19
- exonware/xwsystem/caching/defs.py +2 -1
- exonware/xwsystem/caching/disk_cache.py +2 -1
- exonware/xwsystem/caching/distributed.py +2 -1
- exonware/xwsystem/caching/errors.py +2 -1
- exonware/xwsystem/caching/events.py +110 -27
- exonware/xwsystem/caching/eviction_strategies.py +2 -2
- exonware/xwsystem/caching/external_caching_python.py +701 -0
- exonware/xwsystem/caching/facade.py +253 -0
- exonware/xwsystem/caching/factory.py +300 -0
- exonware/xwsystem/caching/fluent.py +14 -12
- exonware/xwsystem/caching/integrity.py +21 -6
- exonware/xwsystem/caching/lfu_cache.py +2 -1
- exonware/xwsystem/caching/lfu_optimized.py +18 -6
- exonware/xwsystem/caching/lru_cache.py +7 -4
- exonware/xwsystem/caching/memory_bounded.py +2 -2
- exonware/xwsystem/caching/metrics_exporter.py +2 -2
- exonware/xwsystem/caching/observable_cache.py +2 -2
- exonware/xwsystem/caching/pluggable_cache.py +2 -2
- exonware/xwsystem/caching/rate_limiter.py +2 -2
- exonware/xwsystem/caching/read_through.py +2 -2
- exonware/xwsystem/caching/secure_cache.py +81 -28
- exonware/xwsystem/caching/serializable.py +9 -7
- exonware/xwsystem/caching/stats.py +2 -2
- exonware/xwsystem/caching/tagging.py +2 -2
- exonware/xwsystem/caching/ttl_cache.py +4 -3
- exonware/xwsystem/caching/two_tier_cache.py +6 -3
- exonware/xwsystem/caching/utils.py +30 -12
- exonware/xwsystem/caching/validation.py +2 -2
- exonware/xwsystem/caching/warming.py +6 -3
- exonware/xwsystem/caching/write_behind.py +15 -6
- exonware/xwsystem/config/__init__.py +11 -17
- exonware/xwsystem/config/base.py +5 -5
- exonware/xwsystem/config/contracts.py +93 -153
- exonware/xwsystem/config/defaults.py +3 -2
- exonware/xwsystem/config/defs.py +3 -2
- exonware/xwsystem/config/errors.py +2 -5
- exonware/xwsystem/config/logging.py +12 -8
- exonware/xwsystem/config/logging_setup.py +3 -2
- exonware/xwsystem/config/performance.py +73 -391
- exonware/xwsystem/config/performance_modes.py +9 -8
- exonware/xwsystem/config/version_manager.py +1 -0
- exonware/xwsystem/config.py +27 -0
- exonware/xwsystem/console/__init__.py +53 -0
- exonware/xwsystem/console/base.py +133 -0
- exonware/xwsystem/console/cli/__init__.py +61 -0
- exonware/xwsystem/{cli → console/cli}/args.py +27 -24
- exonware/xwsystem/{cli → console/cli}/base.py +18 -87
- exonware/xwsystem/{cli → console/cli}/colors.py +15 -13
- exonware/xwsystem/console/cli/console.py +98 -0
- exonware/xwsystem/{cli → console/cli}/contracts.py +51 -69
- exonware/xwsystem/console/cli/defs.py +87 -0
- exonware/xwsystem/console/cli/encoding.py +69 -0
- exonware/xwsystem/{cli → console/cli}/errors.py +8 -3
- exonware/xwsystem/console/cli/event_logger.py +166 -0
- exonware/xwsystem/{cli → console/cli}/progress.py +25 -21
- exonware/xwsystem/{cli → console/cli}/prompts.py +3 -2
- exonware/xwsystem/{cli → console/cli}/tables.py +27 -24
- exonware/xwsystem/console/contracts.py +113 -0
- exonware/xwsystem/console/defs.py +154 -0
- exonware/xwsystem/console/errors.py +34 -0
- exonware/xwsystem/console/event_logger.py +385 -0
- exonware/xwsystem/console/writer.py +132 -0
- exonware/xwsystem/contracts.py +28 -0
- exonware/xwsystem/data_structures/__init__.py +23 -0
- exonware/xwsystem/data_structures/trie.py +34 -0
- exonware/xwsystem/data_structures/union_find.py +144 -0
- exonware/xwsystem/defs.py +17 -0
- exonware/xwsystem/errors.py +23 -0
- exonware/xwsystem/facade.py +62 -0
- exonware/xwsystem/http_client/__init__.py +22 -1
- exonware/xwsystem/http_client/advanced_client.py +8 -5
- exonware/xwsystem/http_client/base.py +3 -2
- exonware/xwsystem/http_client/client.py +7 -4
- exonware/xwsystem/http_client/contracts.py +42 -56
- exonware/xwsystem/http_client/defs.py +2 -1
- exonware/xwsystem/http_client/errors.py +2 -1
- exonware/xwsystem/http_client/facade.py +156 -0
- exonware/xwsystem/io/__init__.py +22 -3
- exonware/xwsystem/io/archive/__init__.py +8 -2
- exonware/xwsystem/io/archive/archive.py +1 -1
- exonware/xwsystem/io/archive/archive_files.py +4 -7
- exonware/xwsystem/io/archive/archivers.py +120 -10
- exonware/xwsystem/io/archive/base.py +4 -5
- exonware/xwsystem/io/archive/codec_integration.py +1 -2
- exonware/xwsystem/io/archive/compression.py +1 -2
- exonware/xwsystem/io/archive/facade.py +263 -0
- exonware/xwsystem/io/archive/formats/__init__.py +2 -3
- exonware/xwsystem/io/archive/formats/brotli_format.py +20 -7
- exonware/xwsystem/io/archive/formats/lz4_format.py +20 -7
- exonware/xwsystem/io/archive/formats/rar.py +11 -5
- exonware/xwsystem/io/archive/formats/sevenzip.py +12 -6
- exonware/xwsystem/io/archive/formats/squashfs_format.py +1 -2
- exonware/xwsystem/io/archive/formats/tar.py +52 -7
- exonware/xwsystem/io/archive/formats/wim_format.py +11 -5
- exonware/xwsystem/io/archive/formats/zip.py +1 -2
- exonware/xwsystem/io/archive/formats/zpaq_format.py +1 -2
- exonware/xwsystem/io/archive/formats/zstandard.py +20 -7
- exonware/xwsystem/io/base.py +119 -115
- exonware/xwsystem/io/codec/__init__.py +4 -2
- exonware/xwsystem/io/codec/base.py +19 -13
- exonware/xwsystem/io/codec/contracts.py +59 -2
- exonware/xwsystem/io/codec/registry.py +67 -21
- exonware/xwsystem/io/common/__init__.py +1 -1
- exonware/xwsystem/io/common/atomic.py +29 -16
- exonware/xwsystem/io/common/base.py +11 -10
- exonware/xwsystem/io/common/lock.py +6 -5
- exonware/xwsystem/io/common/path_manager.py +2 -1
- exonware/xwsystem/io/common/watcher.py +1 -2
- exonware/xwsystem/io/contracts.py +301 -433
- exonware/xwsystem/io/contracts_1.py +1180 -0
- exonware/xwsystem/io/data_operations.py +279 -14
- exonware/xwsystem/io/defs.py +4 -3
- exonware/xwsystem/io/errors.py +3 -2
- exonware/xwsystem/io/facade.py +87 -61
- exonware/xwsystem/io/file/__init__.py +1 -1
- exonware/xwsystem/io/file/base.py +8 -9
- exonware/xwsystem/io/file/conversion.py +2 -3
- exonware/xwsystem/io/file/file.py +61 -18
- exonware/xwsystem/io/file/paged_source.py +8 -8
- exonware/xwsystem/io/file/paging/__init__.py +1 -2
- exonware/xwsystem/io/file/paging/byte_paging.py +4 -5
- exonware/xwsystem/io/file/paging/line_paging.py +2 -3
- exonware/xwsystem/io/file/paging/record_paging.py +2 -3
- exonware/xwsystem/io/file/paging/registry.py +1 -2
- exonware/xwsystem/io/file/source.py +13 -17
- exonware/xwsystem/io/filesystem/__init__.py +1 -1
- exonware/xwsystem/io/filesystem/base.py +1 -2
- exonware/xwsystem/io/filesystem/local.py +3 -4
- exonware/xwsystem/io/folder/__init__.py +1 -1
- exonware/xwsystem/io/folder/base.py +1 -2
- exonware/xwsystem/io/folder/folder.py +16 -7
- exonware/xwsystem/io/indexing/__init__.py +14 -0
- exonware/xwsystem/io/indexing/facade.py +443 -0
- exonware/xwsystem/io/path_parser.py +98 -0
- exonware/xwsystem/io/serialization/__init__.py +21 -3
- exonware/xwsystem/io/serialization/auto_serializer.py +146 -20
- exonware/xwsystem/io/serialization/base.py +84 -34
- exonware/xwsystem/io/serialization/contracts.py +50 -73
- exonware/xwsystem/io/serialization/defs.py +2 -1
- exonware/xwsystem/io/serialization/errors.py +2 -1
- exonware/xwsystem/io/serialization/flyweight.py +154 -7
- exonware/xwsystem/io/serialization/format_detector.py +15 -14
- exonware/xwsystem/io/serialization/formats/__init__.py +8 -5
- exonware/xwsystem/io/serialization/formats/binary/bson.py +15 -6
- exonware/xwsystem/io/serialization/formats/binary/cbor.py +5 -5
- exonware/xwsystem/io/serialization/formats/binary/marshal.py +5 -5
- exonware/xwsystem/io/serialization/formats/binary/msgpack.py +5 -5
- exonware/xwsystem/io/serialization/formats/binary/pickle.py +5 -5
- exonware/xwsystem/io/serialization/formats/binary/plistlib.py +5 -5
- exonware/xwsystem/io/serialization/formats/database/dbm.py +7 -7
- exonware/xwsystem/io/serialization/formats/database/shelve.py +7 -7
- exonware/xwsystem/io/serialization/formats/database/sqlite3.py +7 -7
- exonware/xwsystem/io/serialization/formats/tabular/__init__.py +27 -0
- exonware/xwsystem/io/serialization/formats/tabular/base.py +89 -0
- exonware/xwsystem/io/serialization/formats/tabular/csv.py +319 -0
- exonware/xwsystem/io/serialization/formats/tabular/df.py +249 -0
- exonware/xwsystem/io/serialization/formats/tabular/excel.py +291 -0
- exonware/xwsystem/io/serialization/formats/tabular/googlesheets.py +374 -0
- exonware/xwsystem/io/serialization/formats/text/__init__.py +1 -1
- exonware/xwsystem/io/serialization/formats/text/append_only_log.py +199 -0
- exonware/xwsystem/io/serialization/formats/text/configparser.py +5 -5
- exonware/xwsystem/io/serialization/formats/text/csv.py +7 -5
- exonware/xwsystem/io/serialization/formats/text/formdata.py +5 -5
- exonware/xwsystem/io/serialization/formats/text/json.py +65 -33
- exonware/xwsystem/io/serialization/formats/text/json5.py +8 -4
- exonware/xwsystem/io/serialization/formats/text/jsonlines.py +113 -25
- exonware/xwsystem/io/serialization/formats/text/multipart.py +5 -5
- exonware/xwsystem/io/serialization/formats/text/toml.py +8 -6
- exonware/xwsystem/io/serialization/formats/text/xml.py +25 -20
- exonware/xwsystem/io/serialization/formats/text/yaml.py +8 -6
- exonware/xwsystem/io/serialization/parsers/__init__.py +16 -0
- exonware/xwsystem/io/serialization/parsers/base.py +60 -0
- exonware/xwsystem/io/serialization/parsers/hybrid_parser.py +62 -0
- exonware/xwsystem/io/serialization/parsers/msgspec_parser.py +48 -0
- exonware/xwsystem/io/serialization/parsers/orjson_direct_parser.py +54 -0
- exonware/xwsystem/io/serialization/parsers/orjson_parser.py +62 -0
- exonware/xwsystem/io/serialization/parsers/pysimdjson_parser.py +55 -0
- exonware/xwsystem/io/serialization/parsers/rapidjson_parser.py +53 -0
- exonware/xwsystem/io/serialization/parsers/registry.py +91 -0
- exonware/xwsystem/io/serialization/parsers/standard.py +44 -0
- exonware/xwsystem/io/serialization/parsers/ujson_parser.py +53 -0
- exonware/xwsystem/io/serialization/registry.py +4 -4
- exonware/xwsystem/io/serialization/serializer.py +168 -79
- exonware/xwsystem/io/serialization/universal_options.py +367 -0
- exonware/xwsystem/io/serialization/utils/__init__.py +1 -2
- exonware/xwsystem/io/serialization/utils/path_ops.py +5 -6
- exonware/xwsystem/io/source_reader.py +223 -0
- exonware/xwsystem/io/stream/__init__.py +1 -1
- exonware/xwsystem/io/stream/async_operations.py +61 -14
- exonware/xwsystem/io/stream/base.py +1 -2
- exonware/xwsystem/io/stream/codec_io.py +6 -7
- exonware/xwsystem/ipc/__init__.py +1 -0
- exonware/xwsystem/ipc/async_fabric.py +4 -4
- exonware/xwsystem/ipc/base.py +6 -5
- exonware/xwsystem/ipc/contracts.py +41 -66
- exonware/xwsystem/ipc/defs.py +2 -1
- exonware/xwsystem/ipc/errors.py +2 -1
- exonware/xwsystem/ipc/message_queue.py +5 -2
- exonware/xwsystem/ipc/pipes.py +70 -34
- exonware/xwsystem/ipc/process_manager.py +7 -5
- exonware/xwsystem/ipc/process_pool.py +6 -5
- exonware/xwsystem/ipc/shared_memory.py +64 -11
- exonware/xwsystem/monitoring/__init__.py +7 -0
- exonware/xwsystem/monitoring/base.py +11 -8
- exonware/xwsystem/monitoring/contracts.py +86 -144
- exonware/xwsystem/monitoring/defs.py +2 -1
- exonware/xwsystem/monitoring/error_recovery.py +16 -3
- exonware/xwsystem/monitoring/errors.py +2 -1
- exonware/xwsystem/monitoring/facade.py +183 -0
- exonware/xwsystem/monitoring/memory_monitor.py +1 -0
- exonware/xwsystem/monitoring/metrics.py +1 -0
- exonware/xwsystem/monitoring/performance_manager_generic.py +7 -7
- exonware/xwsystem/monitoring/performance_monitor.py +1 -0
- exonware/xwsystem/monitoring/performance_validator.py +1 -0
- exonware/xwsystem/monitoring/system_monitor.py +6 -5
- exonware/xwsystem/monitoring/tracing.py +18 -16
- exonware/xwsystem/monitoring/tracker.py +2 -1
- exonware/xwsystem/operations/__init__.py +5 -50
- exonware/xwsystem/operations/base.py +3 -44
- exonware/xwsystem/operations/contracts.py +25 -15
- exonware/xwsystem/operations/defs.py +1 -1
- exonware/xwsystem/operations/diff.py +5 -4
- exonware/xwsystem/operations/errors.py +1 -1
- exonware/xwsystem/operations/merge.py +6 -4
- exonware/xwsystem/operations/patch.py +5 -4
- exonware/xwsystem/patterns/__init__.py +1 -0
- exonware/xwsystem/patterns/base.py +2 -1
- exonware/xwsystem/patterns/context_manager.py +2 -1
- exonware/xwsystem/patterns/contracts.py +215 -256
- exonware/xwsystem/patterns/defs.py +2 -1
- exonware/xwsystem/patterns/dynamic_facade.py +1 -0
- exonware/xwsystem/patterns/errors.py +2 -4
- exonware/xwsystem/patterns/handler_factory.py +2 -3
- exonware/xwsystem/patterns/import_registry.py +1 -0
- exonware/xwsystem/patterns/object_pool.py +1 -0
- exonware/xwsystem/patterns/registry.py +4 -43
- exonware/xwsystem/plugins/__init__.py +2 -1
- exonware/xwsystem/plugins/base.py +6 -5
- exonware/xwsystem/plugins/contracts.py +94 -158
- exonware/xwsystem/plugins/defs.py +2 -1
- exonware/xwsystem/plugins/errors.py +2 -1
- exonware/xwsystem/py.typed +3 -0
- exonware/xwsystem/query/__init__.py +36 -0
- exonware/xwsystem/query/contracts.py +56 -0
- exonware/xwsystem/query/errors.py +22 -0
- exonware/xwsystem/query/registry.py +128 -0
- exonware/xwsystem/runtime/__init__.py +2 -1
- exonware/xwsystem/runtime/base.py +4 -3
- exonware/xwsystem/runtime/contracts.py +39 -60
- exonware/xwsystem/runtime/defs.py +2 -1
- exonware/xwsystem/runtime/env.py +11 -9
- exonware/xwsystem/runtime/errors.py +2 -1
- exonware/xwsystem/runtime/reflection.py +3 -2
- exonware/xwsystem/security/__init__.py +68 -11
- exonware/xwsystem/security/audit.py +167 -0
- exonware/xwsystem/security/base.py +121 -24
- exonware/xwsystem/security/contracts.py +91 -146
- exonware/xwsystem/security/crypto.py +17 -16
- exonware/xwsystem/security/defs.py +2 -1
- exonware/xwsystem/security/errors.py +2 -1
- exonware/xwsystem/security/facade.py +321 -0
- exonware/xwsystem/security/file_security.py +330 -0
- exonware/xwsystem/security/hazmat.py +11 -8
- exonware/xwsystem/security/monitor.py +372 -0
- exonware/xwsystem/security/path_validator.py +140 -18
- exonware/xwsystem/security/policy.py +357 -0
- exonware/xwsystem/security/resource_limits.py +1 -0
- exonware/xwsystem/security/validator.py +455 -0
- exonware/xwsystem/shared/__init__.py +14 -1
- exonware/xwsystem/shared/base.py +285 -2
- exonware/xwsystem/shared/contracts.py +415 -126
- exonware/xwsystem/shared/defs.py +2 -1
- exonware/xwsystem/shared/errors.py +2 -2
- exonware/xwsystem/shared/xwobject.py +316 -0
- exonware/xwsystem/structures/__init__.py +1 -0
- exonware/xwsystem/structures/base.py +3 -2
- exonware/xwsystem/structures/circular_detector.py +15 -14
- exonware/xwsystem/structures/contracts.py +53 -76
- exonware/xwsystem/structures/defs.py +2 -1
- exonware/xwsystem/structures/errors.py +2 -1
- exonware/xwsystem/structures/tree_walker.py +2 -1
- exonware/xwsystem/threading/__init__.py +21 -4
- exonware/xwsystem/threading/async_primitives.py +6 -5
- exonware/xwsystem/threading/base.py +3 -2
- exonware/xwsystem/threading/contracts.py +87 -143
- exonware/xwsystem/threading/defs.py +2 -1
- exonware/xwsystem/threading/errors.py +2 -1
- exonware/xwsystem/threading/facade.py +175 -0
- exonware/xwsystem/threading/locks.py +1 -0
- exonware/xwsystem/threading/safe_factory.py +1 -0
- exonware/xwsystem/utils/__init__.py +40 -0
- exonware/xwsystem/utils/base.py +22 -21
- exonware/xwsystem/utils/contracts.py +50 -73
- exonware/xwsystem/utils/dt/__init__.py +19 -3
- exonware/xwsystem/utils/dt/base.py +5 -4
- exonware/xwsystem/utils/dt/contracts.py +22 -29
- exonware/xwsystem/utils/dt/defs.py +2 -1
- exonware/xwsystem/utils/dt/errors.py +2 -5
- exonware/xwsystem/utils/dt/formatting.py +88 -2
- exonware/xwsystem/utils/dt/humanize.py +10 -9
- exonware/xwsystem/utils/dt/parsing.py +56 -5
- exonware/xwsystem/utils/dt/timezone_utils.py +2 -24
- exonware/xwsystem/utils/errors.py +2 -4
- exonware/xwsystem/utils/paths.py +1 -0
- exonware/xwsystem/utils/string.py +49 -0
- exonware/xwsystem/utils/test_runner.py +139 -480
- exonware/xwsystem/utils/utils_contracts.py +2 -1
- exonware/xwsystem/utils/web.py +110 -0
- exonware/xwsystem/validation/__init__.py +25 -1
- exonware/xwsystem/validation/base.py +6 -5
- exonware/xwsystem/validation/contracts.py +29 -41
- exonware/xwsystem/validation/data_validator.py +1 -0
- exonware/xwsystem/validation/declarative.py +11 -8
- exonware/xwsystem/validation/defs.py +2 -1
- exonware/xwsystem/validation/errors.py +2 -1
- exonware/xwsystem/validation/facade.py +198 -0
- exonware/xwsystem/validation/fluent_validator.py +22 -19
- exonware/xwsystem/validation/schema_discovery.py +210 -0
- exonware/xwsystem/validation/type_safety.py +2 -1
- exonware/xwsystem/version.py +4 -4
- {exonware_xwsystem-0.0.1.411.dist-info → exonware_xwsystem-0.1.0.3.dist-info}/METADATA +71 -4
- exonware_xwsystem-0.1.0.3.dist-info/RECORD +337 -0
- exonware/xwsystem/caching/USAGE_GUIDE.md +0 -779
- exonware/xwsystem/cli/__init__.py +0 -43
- exonware/xwsystem/cli/console.py +0 -113
- exonware/xwsystem/cli/defs.py +0 -134
- exonware/xwsystem/conf.py +0 -44
- exonware/xwsystem/security/auth.py +0 -484
- exonware_xwsystem-0.0.1.411.dist-info/RECORD +0 -274
- {exonware_xwsystem-0.0.1.411.dist-info → exonware_xwsystem-0.1.0.3.dist-info}/WHEEL +0 -0
- {exonware_xwsystem-0.0.1.411.dist-info → exonware_xwsystem-0.1.0.3.dist-info}/licenses/LICENSE +0 -0
|
@@ -1,8 +1,9 @@
|
|
|
1
|
+
#exonware/xwsystem/src/exonware/xwsystem/security/crypto.py
|
|
1
2
|
"""
|
|
2
3
|
Company: eXonware.com
|
|
3
4
|
Author: Eng. Muhammad AlShehri
|
|
4
5
|
Email: connect@exonware.com
|
|
5
|
-
Version: 0.0.
|
|
6
|
+
Version: 0.1.0.3
|
|
6
7
|
Generation Date: September 04, 2025
|
|
7
8
|
|
|
8
9
|
Cryptographic utilities for secure data handling and protection.
|
|
@@ -13,7 +14,7 @@ import hmac
|
|
|
13
14
|
import secrets
|
|
14
15
|
import time
|
|
15
16
|
from base64 import b64decode, b64encode
|
|
16
|
-
from typing import Any, Optional
|
|
17
|
+
from typing import Any, Optional
|
|
17
18
|
|
|
18
19
|
from cryptography.fernet import Fernet
|
|
19
20
|
from cryptography.hazmat.primitives import hashes, serialization
|
|
@@ -31,7 +32,7 @@ class SecureHash:
|
|
|
31
32
|
"""Secure hashing utilities."""
|
|
32
33
|
|
|
33
34
|
@staticmethod
|
|
34
|
-
def sha256(data:
|
|
35
|
+
def sha256(data: str | bytes) -> str:
|
|
35
36
|
"""
|
|
36
37
|
Compute SHA-256 hash.
|
|
37
38
|
|
|
@@ -46,7 +47,7 @@ class SecureHash:
|
|
|
46
47
|
return hashlib.sha256(data).hexdigest()
|
|
47
48
|
|
|
48
49
|
@staticmethod
|
|
49
|
-
def sha512(data:
|
|
50
|
+
def sha512(data: str | bytes) -> str:
|
|
50
51
|
"""
|
|
51
52
|
Compute SHA-512 hash.
|
|
52
53
|
|
|
@@ -61,7 +62,7 @@ class SecureHash:
|
|
|
61
62
|
return hashlib.sha512(data).hexdigest()
|
|
62
63
|
|
|
63
64
|
@staticmethod
|
|
64
|
-
def blake2b(data:
|
|
65
|
+
def blake2b(data: str | bytes, key: Optional[bytes] = None) -> str:
|
|
65
66
|
"""
|
|
66
67
|
Compute BLAKE2b hash.
|
|
67
68
|
|
|
@@ -80,7 +81,7 @@ class SecureHash:
|
|
|
80
81
|
return hashlib.blake2b(data, key=key).hexdigest()
|
|
81
82
|
|
|
82
83
|
@staticmethod
|
|
83
|
-
def hmac_sha256(data:
|
|
84
|
+
def hmac_sha256(data: str | bytes, key: str | bytes) -> str:
|
|
84
85
|
"""
|
|
85
86
|
Compute HMAC-SHA256.
|
|
86
87
|
|
|
@@ -98,7 +99,7 @@ class SecureHash:
|
|
|
98
99
|
return hmac.new(key, data, hashlib.sha256).hexdigest()
|
|
99
100
|
|
|
100
101
|
@staticmethod
|
|
101
|
-
def verify_hmac(data:
|
|
102
|
+
def verify_hmac(data: str | bytes, key: str | bytes, expected_hmac: str) -> bool:
|
|
102
103
|
"""
|
|
103
104
|
Verify HMAC-SHA256.
|
|
104
105
|
|
|
@@ -231,7 +232,7 @@ class SymmetricEncryption:
|
|
|
231
232
|
key = b64encode(kdf.derive(password.encode('utf-8')))
|
|
232
233
|
return key, salt
|
|
233
234
|
|
|
234
|
-
def encrypt(self, data:
|
|
235
|
+
def encrypt(self, data: str | bytes) -> bytes:
|
|
235
236
|
"""
|
|
236
237
|
Encrypt data.
|
|
237
238
|
|
|
@@ -337,7 +338,7 @@ class AsymmetricEncryption:
|
|
|
337
338
|
instance = cls(private_pem, public_pem)
|
|
338
339
|
return instance, private_pem, public_pem
|
|
339
340
|
|
|
340
|
-
def encrypt(self, data:
|
|
341
|
+
def encrypt(self, data: str | bytes) -> bytes:
|
|
341
342
|
"""
|
|
342
343
|
Encrypt data with public key.
|
|
343
344
|
|
|
@@ -384,7 +385,7 @@ class AsymmetricEncryption:
|
|
|
384
385
|
)
|
|
385
386
|
)
|
|
386
387
|
|
|
387
|
-
def sign(self, data:
|
|
388
|
+
def sign(self, data: str | bytes) -> bytes:
|
|
388
389
|
"""
|
|
389
390
|
Sign data with private key.
|
|
390
391
|
|
|
@@ -409,7 +410,7 @@ class AsymmetricEncryption:
|
|
|
409
410
|
hashes.SHA256()
|
|
410
411
|
)
|
|
411
412
|
|
|
412
|
-
def verify(self, data:
|
|
413
|
+
def verify(self, data: str | bytes, signature: bytes) -> bool:
|
|
413
414
|
"""
|
|
414
415
|
Verify signature with public key.
|
|
415
416
|
|
|
@@ -627,7 +628,7 @@ def _hash_password_pbkdf2(password: str) -> str:
|
|
|
627
628
|
|
|
628
629
|
# Generate random salt
|
|
629
630
|
salt = secrets.token_bytes(32)
|
|
630
|
-
iterations = 100000 # OWASP
|
|
631
|
+
iterations = 100000 # OWASP minimum
|
|
631
632
|
|
|
632
633
|
# Derive key using PBKDF2
|
|
633
634
|
kdf = PBKDF2HMAC(
|
|
@@ -781,7 +782,7 @@ class AsyncSymmetricEncryption:
|
|
|
781
782
|
"""Get the encryption key."""
|
|
782
783
|
return self._encryption.key
|
|
783
784
|
|
|
784
|
-
async def encrypt(self, data:
|
|
785
|
+
async def encrypt(self, data: str | bytes) -> bytes:
|
|
785
786
|
"""Encrypt data (async)."""
|
|
786
787
|
import asyncio
|
|
787
788
|
return await asyncio.to_thread(self._encryption.encrypt, data)
|
|
@@ -819,7 +820,7 @@ class AsyncAsymmetricEncryption:
|
|
|
819
820
|
async_encryption = cls(private_pem, public_pem)
|
|
820
821
|
return async_encryption, private_pem, public_pem
|
|
821
822
|
|
|
822
|
-
async def encrypt(self, data:
|
|
823
|
+
async def encrypt(self, data: str | bytes) -> bytes:
|
|
823
824
|
"""Encrypt data with public key (async)."""
|
|
824
825
|
import asyncio
|
|
825
826
|
return await asyncio.to_thread(self._encryption.encrypt, data)
|
|
@@ -829,12 +830,12 @@ class AsyncAsymmetricEncryption:
|
|
|
829
830
|
import asyncio
|
|
830
831
|
return await asyncio.to_thread(self._encryption.decrypt, encrypted_data)
|
|
831
832
|
|
|
832
|
-
async def sign(self, data:
|
|
833
|
+
async def sign(self, data: str | bytes) -> bytes:
|
|
833
834
|
"""Sign data with private key (async)."""
|
|
834
835
|
import asyncio
|
|
835
836
|
return await asyncio.to_thread(self._encryption.sign, data)
|
|
836
837
|
|
|
837
|
-
async def verify(self, data:
|
|
838
|
+
async def verify(self, data: str | bytes, signature: bytes) -> bool:
|
|
838
839
|
"""Verify signature with public key (async)."""
|
|
839
840
|
import asyncio
|
|
840
841
|
return await asyncio.to_thread(self._encryption.verify, data, signature)
|
|
@@ -1,10 +1,11 @@
|
|
|
1
1
|
#!/usr/bin/env python3
|
|
2
|
+
#exonware/xwsystem/src/exonware/xwsystem/security/defs.py
|
|
2
3
|
#exonware/xwsystem/security/types.py
|
|
3
4
|
"""
|
|
4
5
|
Company: eXonware.com
|
|
5
6
|
Author: Eng. Muhammad AlShehri
|
|
6
7
|
Email: connect@exonware.com
|
|
7
|
-
Version: 0.0.
|
|
8
|
+
Version: 0.1.0.3
|
|
8
9
|
Generation Date: 07-Sep-2025
|
|
9
10
|
|
|
10
11
|
Security types and enums for XWSystem.
|
|
@@ -1,9 +1,10 @@
|
|
|
1
|
+
#exonware/xwsystem/src/exonware/xwsystem/security/errors.py
|
|
1
2
|
#exonware/xwsystem/security/errors.py
|
|
2
3
|
"""
|
|
3
4
|
Company: eXonware.com
|
|
4
5
|
Author: Eng. Muhammad AlShehri
|
|
5
6
|
Email: connect@exonware.com
|
|
6
|
-
Version: 0.0.
|
|
7
|
+
Version: 0.1.0.3
|
|
7
8
|
Generation Date: September 04, 2025
|
|
8
9
|
|
|
9
10
|
Security module errors - exception classes for security functionality.
|
|
@@ -0,0 +1,321 @@
|
|
|
1
|
+
#exonware/xwsystem/src/exonware/xwsystem/security/facade.py
|
|
2
|
+
"""
|
|
3
|
+
Company: eXonware.com
|
|
4
|
+
Author: Eng. Muhammad AlShehri
|
|
5
|
+
Email: connect@exonware.com
|
|
6
|
+
Version: 0.1.0.3
|
|
7
|
+
Generation Date: January 2026
|
|
8
|
+
|
|
9
|
+
XWSecurity & XWCrypto - Unified Security Facades
|
|
10
|
+
|
|
11
|
+
Simplified API for security operations:
|
|
12
|
+
- Hashing (SHA-256, SHA-512, BLAKE2b, HMAC)
|
|
13
|
+
- Password hashing and verification
|
|
14
|
+
- Encryption (Symmetric, Asymmetric)
|
|
15
|
+
- Secure storage
|
|
16
|
+
- Path validation
|
|
17
|
+
"""
|
|
18
|
+
|
|
19
|
+
from typing import Any, Optional, Tuple
|
|
20
|
+
|
|
21
|
+
from .crypto import (
|
|
22
|
+
SecureHash,
|
|
23
|
+
SecureRandom,
|
|
24
|
+
SymmetricEncryption,
|
|
25
|
+
AsymmetricEncryption,
|
|
26
|
+
SecureStorage,
|
|
27
|
+
AsyncSecureStorage,
|
|
28
|
+
AsyncSymmetricEncryption,
|
|
29
|
+
AsyncAsymmetricEncryption,
|
|
30
|
+
hash_password,
|
|
31
|
+
verify_password,
|
|
32
|
+
generate_api_key,
|
|
33
|
+
generate_session_token,
|
|
34
|
+
)
|
|
35
|
+
from .path_validator import PathValidator, PathSecurityError
|
|
36
|
+
from ..config.logging_setup import get_logger
|
|
37
|
+
|
|
38
|
+
logger = get_logger(__name__)
|
|
39
|
+
|
|
40
|
+
|
|
41
|
+
class XWSecurity:
|
|
42
|
+
"""
|
|
43
|
+
Unified security facade - simple API for security operations.
|
|
44
|
+
|
|
45
|
+
Examples:
|
|
46
|
+
>>> # Hashing
|
|
47
|
+
>>> hash_value = XWSecurity.hash("password", algorithm="sha256")
|
|
48
|
+
>>> is_valid = XWSecurity.verify_hash("password", hash_value)
|
|
49
|
+
|
|
50
|
+
>>> # Password hashing
|
|
51
|
+
>>> hashed = XWSecurity.hash_password("mypassword")
|
|
52
|
+
>>> XWSecurity.verify_password("mypassword", hashed)
|
|
53
|
+
|
|
54
|
+
>>> # Path validation
|
|
55
|
+
>>> XWSecurity.validate_path("/safe/dir/file.txt", base_path="/safe")
|
|
56
|
+
|
|
57
|
+
>>> # Secure storage
|
|
58
|
+
>>> storage = XWSecurity.Storage()
|
|
59
|
+
>>> storage.set("api_key", "sk_...")
|
|
60
|
+
>>> value = storage.get("api_key")
|
|
61
|
+
"""
|
|
62
|
+
|
|
63
|
+
@staticmethod
|
|
64
|
+
def hash(data: str | bytes, algorithm: str = "sha256") -> str:
|
|
65
|
+
"""
|
|
66
|
+
Hash data with specified algorithm.
|
|
67
|
+
|
|
68
|
+
Args:
|
|
69
|
+
data: Data to hash
|
|
70
|
+
algorithm: Hash algorithm ("sha256", "sha512", "blake2b", "hmac_sha256")
|
|
71
|
+
|
|
72
|
+
Returns:
|
|
73
|
+
Hex digest string
|
|
74
|
+
"""
|
|
75
|
+
if algorithm == "sha256":
|
|
76
|
+
return SecureHash.sha256(data)
|
|
77
|
+
elif algorithm == "sha512":
|
|
78
|
+
return SecureHash.sha512(data)
|
|
79
|
+
elif algorithm == "blake2b":
|
|
80
|
+
return SecureHash.blake2b(data)
|
|
81
|
+
else:
|
|
82
|
+
raise ValueError(f"Unknown algorithm: {algorithm}")
|
|
83
|
+
|
|
84
|
+
@staticmethod
|
|
85
|
+
def verify_hash(data: str | bytes, hash_value: str, algorithm: str = "sha256") -> bool:
|
|
86
|
+
"""
|
|
87
|
+
Verify hash matches data.
|
|
88
|
+
|
|
89
|
+
Args:
|
|
90
|
+
data: Original data
|
|
91
|
+
hash_value: Hash to verify against
|
|
92
|
+
algorithm: Hash algorithm used
|
|
93
|
+
|
|
94
|
+
Returns:
|
|
95
|
+
True if hash matches
|
|
96
|
+
"""
|
|
97
|
+
computed = XWSecurity.hash(data, algorithm)
|
|
98
|
+
return computed == hash_value
|
|
99
|
+
|
|
100
|
+
@staticmethod
|
|
101
|
+
def hash_password(password: str, rounds: int = 12) -> str:
|
|
102
|
+
"""
|
|
103
|
+
Hash password securely.
|
|
104
|
+
|
|
105
|
+
Args:
|
|
106
|
+
password: Password to hash
|
|
107
|
+
rounds: Bcrypt rounds (default: 12)
|
|
108
|
+
|
|
109
|
+
Returns:
|
|
110
|
+
Hashed password string
|
|
111
|
+
"""
|
|
112
|
+
return hash_password(password, rounds)
|
|
113
|
+
|
|
114
|
+
@staticmethod
|
|
115
|
+
def verify_password(password: str, hashed_password: str) -> bool:
|
|
116
|
+
"""
|
|
117
|
+
Verify password against hash.
|
|
118
|
+
|
|
119
|
+
Args:
|
|
120
|
+
password: Plain password
|
|
121
|
+
hashed_password: Hashed password
|
|
122
|
+
|
|
123
|
+
Returns:
|
|
124
|
+
True if password matches
|
|
125
|
+
"""
|
|
126
|
+
return verify_password(password, hashed_password)
|
|
127
|
+
|
|
128
|
+
@staticmethod
|
|
129
|
+
def validate_path(path: str, base_path: Optional[str] = None) -> str:
|
|
130
|
+
"""
|
|
131
|
+
Validate and sanitize file path.
|
|
132
|
+
|
|
133
|
+
Args:
|
|
134
|
+
path: Path to validate
|
|
135
|
+
base_path: Base directory (prevents directory traversal)
|
|
136
|
+
|
|
137
|
+
Returns:
|
|
138
|
+
Validated path
|
|
139
|
+
|
|
140
|
+
Raises:
|
|
141
|
+
PathSecurityError: If path is invalid
|
|
142
|
+
"""
|
|
143
|
+
validator = PathValidator(base_path) if base_path else PathValidator()
|
|
144
|
+
return validator.validate_path(path)
|
|
145
|
+
|
|
146
|
+
@staticmethod
|
|
147
|
+
def generate_api_key(length: int = 32) -> str:
|
|
148
|
+
"""Generate cryptographically secure API key."""
|
|
149
|
+
return generate_api_key(length)
|
|
150
|
+
|
|
151
|
+
@staticmethod
|
|
152
|
+
def generate_session_token(length: int = 32) -> str:
|
|
153
|
+
"""Generate cryptographically secure session token."""
|
|
154
|
+
return generate_session_token(length)
|
|
155
|
+
|
|
156
|
+
class Storage:
|
|
157
|
+
"""Secure encrypted key-value storage."""
|
|
158
|
+
|
|
159
|
+
def __init__(self, password: Optional[str] = None):
|
|
160
|
+
"""
|
|
161
|
+
Initialize secure storage.
|
|
162
|
+
|
|
163
|
+
Args:
|
|
164
|
+
password: Optional password for encryption (auto-generated if None)
|
|
165
|
+
"""
|
|
166
|
+
self._storage = SecureStorage() if password is None else SecureStorage.from_password(password)
|
|
167
|
+
|
|
168
|
+
def set(self, key: str, value: Any) -> None:
|
|
169
|
+
"""Store encrypted value."""
|
|
170
|
+
self._storage.store(key, value)
|
|
171
|
+
|
|
172
|
+
def get(self, key: str) -> Any:
|
|
173
|
+
"""Retrieve and decrypt value."""
|
|
174
|
+
return self._storage.retrieve(key)
|
|
175
|
+
|
|
176
|
+
def delete(self, key: str) -> bool:
|
|
177
|
+
"""Delete stored value."""
|
|
178
|
+
return self._storage.delete(key)
|
|
179
|
+
|
|
180
|
+
|
|
181
|
+
class XWCrypto:
|
|
182
|
+
"""
|
|
183
|
+
Unified cryptography facade - simple API for encryption operations.
|
|
184
|
+
|
|
185
|
+
Examples:
|
|
186
|
+
>>> # Symmetric encryption
|
|
187
|
+
>>> crypto = XWCrypto() # Auto-generates key
|
|
188
|
+
>>> encrypted = crypto.encrypt("secret data")
|
|
189
|
+
>>> decrypted = crypto.decrypt(encrypted)
|
|
190
|
+
|
|
191
|
+
>>> # Password-based encryption
|
|
192
|
+
>>> crypto = XWCrypto.from_password("mypassword")
|
|
193
|
+
>>> encrypted = crypto.encrypt("data")
|
|
194
|
+
|
|
195
|
+
>>> # Asymmetric encryption
|
|
196
|
+
>>> public, private = XWCrypto.generate_key_pair()
|
|
197
|
+
>>> encrypted = XWCrypto.encrypt("data", public_key=public)
|
|
198
|
+
>>> decrypted = XWCrypto.decrypt(encrypted, private_key=private)
|
|
199
|
+
"""
|
|
200
|
+
|
|
201
|
+
def __init__(self, key: Optional[bytes] = None):
|
|
202
|
+
"""
|
|
203
|
+
Initialize crypto with key.
|
|
204
|
+
|
|
205
|
+
Args:
|
|
206
|
+
key: Optional encryption key (auto-generated if None)
|
|
207
|
+
"""
|
|
208
|
+
if key is None:
|
|
209
|
+
self._crypto = SymmetricEncryption()
|
|
210
|
+
self._key = self._crypto.key
|
|
211
|
+
else:
|
|
212
|
+
self._crypto = SymmetricEncryption(key)
|
|
213
|
+
self._key = key
|
|
214
|
+
|
|
215
|
+
@classmethod
|
|
216
|
+
def from_password(cls, password: str) -> "XWCrypto":
|
|
217
|
+
"""
|
|
218
|
+
Create crypto instance from password.
|
|
219
|
+
|
|
220
|
+
Args:
|
|
221
|
+
password: Password for key derivation
|
|
222
|
+
|
|
223
|
+
Returns:
|
|
224
|
+
XWCrypto instance
|
|
225
|
+
"""
|
|
226
|
+
instance = cls.__new__(cls)
|
|
227
|
+
# Derive key from password
|
|
228
|
+
key, _ = SymmetricEncryption.derive_key_from_password(password)
|
|
229
|
+
instance._crypto = SymmetricEncryption(key)
|
|
230
|
+
instance._key = key
|
|
231
|
+
return instance
|
|
232
|
+
|
|
233
|
+
def encrypt(self, data: str | bytes) -> bytes:
|
|
234
|
+
"""Encrypt data using instance's crypto."""
|
|
235
|
+
return self._crypto.encrypt(data)
|
|
236
|
+
|
|
237
|
+
def decrypt(self, encrypted_data: bytes) -> str | bytes:
|
|
238
|
+
"""Decrypt data using instance's crypto."""
|
|
239
|
+
return self._crypto.decrypt(encrypted_data)
|
|
240
|
+
|
|
241
|
+
@property
|
|
242
|
+
def key(self) -> bytes:
|
|
243
|
+
"""Get encryption key."""
|
|
244
|
+
return self._key
|
|
245
|
+
|
|
246
|
+
@staticmethod
|
|
247
|
+
def encrypt_static(data: str | bytes, password: Optional[str] = None, public_key: Optional[bytes] = None, key: Optional[bytes] = None) -> bytes:
|
|
248
|
+
"""
|
|
249
|
+
Static method to encrypt data.
|
|
250
|
+
|
|
251
|
+
Args:
|
|
252
|
+
data: Data to encrypt
|
|
253
|
+
password: Password for symmetric encryption (key derivation)
|
|
254
|
+
public_key: Public key for asymmetric encryption
|
|
255
|
+
key: Direct encryption key (for symmetric)
|
|
256
|
+
|
|
257
|
+
Returns:
|
|
258
|
+
Encrypted data
|
|
259
|
+
"""
|
|
260
|
+
if public_key:
|
|
261
|
+
crypto = AsymmetricEncryption(public_key=public_key)
|
|
262
|
+
return crypto.encrypt(data)
|
|
263
|
+
elif password:
|
|
264
|
+
# Use deterministic salt based on password for consistent encryption/decryption
|
|
265
|
+
# Note: This is less secure than random salt but allows same password to work
|
|
266
|
+
import hashlib
|
|
267
|
+
salt = hashlib.sha256(password.encode()).digest()[:16] # Deterministic salt
|
|
268
|
+
key, _ = SymmetricEncryption.derive_key_from_password(password, salt=salt)
|
|
269
|
+
crypto = SymmetricEncryption(key)
|
|
270
|
+
return crypto.encrypt(data)
|
|
271
|
+
elif key:
|
|
272
|
+
crypto = SymmetricEncryption(key)
|
|
273
|
+
return crypto.encrypt(data)
|
|
274
|
+
else:
|
|
275
|
+
# Auto-generate key for one-time encryption
|
|
276
|
+
crypto = SymmetricEncryption()
|
|
277
|
+
return crypto.encrypt(data)
|
|
278
|
+
|
|
279
|
+
@staticmethod
|
|
280
|
+
def decrypt_static(encrypted_data: bytes, password: Optional[str] = None, private_key: Optional[bytes] = None, key: Optional[bytes] = None) -> bytes:
|
|
281
|
+
"""
|
|
282
|
+
Static method to decrypt data.
|
|
283
|
+
|
|
284
|
+
Args:
|
|
285
|
+
encrypted_data: Encrypted data
|
|
286
|
+
password: Password for symmetric decryption (key derivation)
|
|
287
|
+
private_key: Private key for asymmetric decryption
|
|
288
|
+
key: Direct decryption key (for symmetric)
|
|
289
|
+
|
|
290
|
+
Returns:
|
|
291
|
+
Decrypted data
|
|
292
|
+
"""
|
|
293
|
+
if private_key:
|
|
294
|
+
crypto = AsymmetricEncryption(private_key=private_key)
|
|
295
|
+
return crypto.decrypt(encrypted_data)
|
|
296
|
+
elif password:
|
|
297
|
+
# Use same deterministic salt for decryption
|
|
298
|
+
import hashlib
|
|
299
|
+
salt = hashlib.sha256(password.encode()).digest()[:16] # Deterministic salt
|
|
300
|
+
key, _ = SymmetricEncryption.derive_key_from_password(password, salt=salt)
|
|
301
|
+
crypto = SymmetricEncryption(key)
|
|
302
|
+
return crypto.decrypt(encrypted_data)
|
|
303
|
+
elif key:
|
|
304
|
+
crypto = SymmetricEncryption(key)
|
|
305
|
+
return crypto.decrypt(encrypted_data)
|
|
306
|
+
else:
|
|
307
|
+
raise ValueError("Either password, key, or private_key must be provided")
|
|
308
|
+
|
|
309
|
+
@staticmethod
|
|
310
|
+
def generate_key_pair(key_size: int = 2048) -> Tuple[bytes, bytes]:
|
|
311
|
+
"""
|
|
312
|
+
Generate RSA key pair.
|
|
313
|
+
|
|
314
|
+
Args:
|
|
315
|
+
key_size: Key size in bits (default: 2048)
|
|
316
|
+
|
|
317
|
+
Returns:
|
|
318
|
+
Tuple of (public_key, private_key)
|
|
319
|
+
"""
|
|
320
|
+
crypto = AsymmetricEncryption.generate_key_pair(key_size)
|
|
321
|
+
return crypto.public_key, crypto.private_key
|