From 525b273a84295f0a38cc38176a6131f26558cbc2 Mon Sep 17 00:00:00 2001 From: Orange Date: Sun, 4 Jan 2026 11:38:45 +0300 Subject: [PATCH] added stuff --- .../omath/containers/encrypted_variable.hpp | 176 ++++++++++++++++++ tests/CMakeLists.txt | 2 +- tests/general/unit_test_var_encryption.cpp | 20 ++ 3 files changed, 197 insertions(+), 1 deletion(-) create mode 100644 include/omath/containers/encrypted_variable.hpp create mode 100644 tests/general/unit_test_var_encryption.cpp diff --git a/include/omath/containers/encrypted_variable.hpp b/include/omath/containers/encrypted_variable.hpp new file mode 100644 index 0000000..6388fcb --- /dev/null +++ b/include/omath/containers/encrypted_variable.hpp @@ -0,0 +1,176 @@ +// +// Created by Vladislav on 04.01.2026. +// +#pragma once +#include +#include +#include +#include + +#ifdef _MSC_VER +#define OMATH_FORCEINLINE __forceinline +#else +#define OMATH_FORCEINLINE __attribute__((always_inline)) inline +#endif + +namespace omath +{ + template + class Anchor; + + consteval std::uint64_t fnv1a_64(const char* s) + { + std::uint64_t h = 14695981039346656037ull; + while (*s) + { + h ^= static_cast(*s++); + h *= 1099511628211ull; + } + return h; + } + + // SplitMix64 mixer (good quality for seeding / scrambling) + consteval std::uint64_t splitmix64(std::uint64_t x) + { + x += 0x9E3779B97F4A7C15ull; + x = (x ^ (x >> 30)) * 0xBF58476D1CE4E5B9ull; + x = (x ^ (x >> 27)) * 0x94D049BB133111EBull; + return x ^ (x >> 31); + } + + // Choose your policy: + // - If you want reproducible builds, REMOVE __DATE__/__TIME__. + // - If you want "different each build", keep them. + consteval std::uint64_t base_seed() + { + std::uint64_t h = 0; + h ^= fnv1a_64(__FILE__); + h ^= splitmix64(fnv1a_64(__DATE__)); + h ^= splitmix64(fnv1a_64(__TIME__)); + return splitmix64(h); + } + + // Produce a "random" 64-bit value for a given stream index (compile-time) + template + consteval std::uint64_t rand_u64() + { + // Stream is usually __COUNTER__ so each call site differs + return splitmix64(base_seed() + 0xD1B54A32D192ED03ull * (Stream + 1)); + } + + // Unbiased bounded uniform using Lemire's method (uses 128-bit multiply) + consteval std::uint64_t bounded_u64(std::uint64_t x, std::uint64_t bound) + { + // bound must be > 0 + __uint128_t m = static_cast<__uint128_t>(x) * static_cast<__uint128_t>(bound); + return static_cast(m >> 64); + } + + template + consteval std::int64_t rand_uint8t() + { + static_assert(Lo <= Hi); + const std::uint64_t span = static_cast(Hi - Lo) + 1ull; + const std::uint64_t r = rand_u64(); + return static_cast(bounded_u64(r, span)) + Lo; + } + consteval std::uint64_t rand_u64(std::uint64_t seed, std::uint64_t i) + { + return splitmix64(seed + 0xD1B54A32D192ED03ull * (i + 1ull)); + } + + // Convert to int (uses low 32 bits; you can also use high bits if you prefer) + consteval std::uint8_t rand_uint8t(std::uint64_t seed, std::uint64_t i) + { + return static_cast(rand_u64(seed, i)); // narrowing is fine/deterministic + } + + constexpr std::array create_key() + { + std::array key{}; + + for (auto& byte : key) + { + byte = static_cast(rand_u64<__COUNTER__>()); + } + return key; + } + template + consteval std::array make_array_impl(std::index_sequence) + { + return {rand_uint8t(Seed, static_cast(I))...}; + } + + template + consteval std::array make_array() + { + return make_array_impl(std::make_index_sequence{}); + } + template key> + class EncryptedVariable final + { + bool m_is_encrypted{}; + T m_data; + + public: + OMATH_FORCEINLINE constexpr explicit EncryptedVariable(const T& data): m_is_encrypted(true), m_data(data) + { + encrypt(); + } + [[nodiscard]] constexpr bool is_encrypted() const + { + return m_is_encrypted; + } + OMATH_FORCEINLINE constexpr void decrypt() + { + std::span bytes{reinterpret_cast(&m_data), sizeof(m_data)}; + + for (auto& byte : bytes) + for (const auto key_byte : key) + byte ^= key_byte; + m_is_encrypted = false; + } + OMATH_FORCEINLINE constexpr void encrypt() + { + std::span bytes{reinterpret_cast(&m_data), sizeof(m_data)}; + + for (auto& byte : bytes) + for (const auto key_byte : key) + byte ^= key_byte; + m_is_encrypted = true; + } + OMATH_FORCEINLINE constexpr T& value() + { + return m_data; + } + OMATH_FORCEINLINE constexpr const T& value() const + { + return m_data; + } + OMATH_FORCEINLINE ~EncryptedVariable() + { + decrypt(); + } + }; + template + class Anchor + { + public: + OMATH_FORCEINLINE constexpr Anchor(EncryptedVarType& var): m_var(var) + { + m_var.decrypt(); + } + OMATH_FORCEINLINE constexpr ~Anchor() + { + m_var.encrypt(); + } + + private: + EncryptedVarType& m_var; + }; +} // namespace omath + + +#define CT_RAND_ARRAY_INT(N) \ +(::omath::make_array<(N), (::omath::base_seed() ^ static_cast(__COUNTER__))>()) +#define OMATH_DEF_CRYPT_VAR(TYPE, KEY_SIZE) omath::EncryptedVariable \ No newline at end of file diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt index 76ef3a7..9f82b6e 100644 --- a/tests/CMakeLists.txt +++ b/tests/CMakeLists.txt @@ -20,7 +20,7 @@ else() # GTest is being linked as vcpkg package find_package(GTest CONFIG REQUIRED) target_link_libraries(${PROJECT_NAME} PRIVATE GTest::gtest GTest::gtest_main omath::omath) endif() - +target_compile_options(${PROJECT_NAME} PRIVATE -static) if(OMATH_ENABLE_COVERAGE) include(${CMAKE_SOURCE_DIR}/cmake/Coverage.cmake) omath_setup_coverage(${PROJECT_NAME}) diff --git a/tests/general/unit_test_var_encryption.cpp b/tests/general/unit_test_var_encryption.cpp new file mode 100644 index 0000000..07afe2a --- /dev/null +++ b/tests/general/unit_test_var_encryption.cpp @@ -0,0 +1,20 @@ +// +// Created by Vladislav on 04.01.2026. +// +#include "omath/linear_algebra/vector3.hpp" +#include +#include +TEST(Enc, Test) +{ + OMATH_DEF_CRYPT_VAR(omath::Vector3, 128) var{{1.f, 2.f, 3.f}}; + OMATH_DEF_CRYPT_VAR(omath::Vector3, 128) var2{{1.f, 2.f, 3.f}}; + { + omath::Anchor _ = {var}; + omath::Anchor __ = {var2}; + + std::println("Decrypted var1: {}", var.value()); + std::println("Decrypted var2: {}", var2.value()); + } + std::println("Encrypted var1: {}", var.value()); + std::println("Encrypted var2: {}", var2.value()); +} \ No newline at end of file