/** ****************************************************************************** * @file : obfuscate.hpp * @author : Dream * @brief : None * @attention : None * @date : 2024/12/4 ****************************************************************************** */ /* 原文作者:Adam Yaxley */ #pragma once #if __cplusplus >= 202002L #define AY_CONSTEVAL consteval #else #define AY_CONSTEVAL constexpr #endif #ifdef _MSC_VER #define AY_CAT(X,Y) AY_CAT2(X,Y) #define AY_CAT2(X,Y) X##Y #define AY_LINE int(AY_CAT(__LINE__,U)) #else #define AY_LINE __LINE__ #endif #ifndef AY_OBFUSCATE_DEFAULT_KEY //用于混淆字符串的默认 64 位密钥 //这可以通过在之前定义 AY_OBFUSCATE_DEFAULT_KEY 来由用户指定 //包括 obfuscate.h #define AY_OBFUSCATE_DEFAULT_KEY ay::generate_key(AY_LINE) #endif namespace ay { using size_type = unsigned long long; using key_type = unsigned long long; template struct remove_const_ref { using type = T; }; template struct remove_const_ref { using type = T; }; template struct remove_const_ref { using type = T; }; template struct remove_const_ref { using type = T; }; template using char_type = typename remove_const_ref::type; //生成一个跨越所有 8 个字节的伪随机键 AY_CONSTEVAL key_type generate_key(key_type seed) { // 使用 MurmurHash3 64 位终结器对种子进行哈希处理 key_type key = seed; key ^= (key >> 33); key *= 0xff51afd7ed558ccd; key ^= (key >> 33); key *= 0xc4ceb9fe1a85ec53; key ^= (key >> 33); // 确保设置每个字节中的位 key |= 0x0101010101010101ull; return key; } // 使用 key 对数据进行混淆或反混淆 template constexpr void cipher(CHAR_TYPE* data, size_type size, key_type key) { // 使用基于密钥的简单 XOR 密码进行混淆 for (size_type i = 0; i < size; i++) { data[i] ^= CHAR_TYPE((key >> ((i % 8) * 8)) & 0xFF); } } // 在编译时对字符串进行模糊处理 template class obfuscator { public: // 在构造时混淆字符串 'data' AY_CONSTEVAL obfuscator(const CHAR_TYPE* data) { // Copy data for (size_type i = 0; i < N; i++) { m_data[i] = data[i]; } // On construction each of the characters in the string is // obfuscated with an XOR cipher based on key cipher(m_data, N, KEY); } constexpr const CHAR_TYPE* data() const { return &m_data[0]; } AY_CONSTEVAL size_type size() const { return N; } AY_CONSTEVAL key_type key() const { return KEY; } private: CHAR_TYPE m_data[N]{}; }; // Handles decryption and re-encryption of an encrypted string at runtime template class obfuscated_data { public: obfuscated_data(const obfuscator& obfuscator) { // Copy obfuscated data for (size_type i = 0; i < N; i++) { m_data[i] = obfuscator.data()[i]; } } ~obfuscated_data() { // Zero m_data to remove it from memory for (size_type i = 0; i < N; i++) { m_data[i] = 0; } } // Returns a pointer to the plain text string, decrypting it if // necessary operator CHAR_TYPE* () { decrypt(); return m_data; } // Manually decrypt the string void decrypt() { if (m_encrypted) { cipher(m_data, N, KEY); m_encrypted = false; } } // Manually re-encrypt the string void encrypt() { if (!m_encrypted) { cipher(m_data, N, KEY); m_encrypted = true; } } // Returns true if this string is currently encrypted, false otherwise. bool is_encrypted() const { return m_encrypted; } private: // Local storage for the string. Call is_encrypted() to check whether or // not the string is currently obfuscated. CHAR_TYPE m_data[N]; // Whether data is currently encrypted bool m_encrypted{ true }; }; // This function exists purely to extract the number of elements 'N' in the // array 'data' template AY_CONSTEVAL auto make_obfuscator(const CHAR_TYPE(&data)[N]) { return obfuscator(data); } } #define AY_OBFUSCATE(data) AY_OBFUSCATE_KEY(data, AY_OBFUSCATE_DEFAULT_KEY) #define AY_OBFUSCATE_KEY(data, key) \ []() -> ay::obfuscated_data>& { \ static_assert(sizeof(decltype(key)) == sizeof(ay::key_type), "key must be a 64 bit unsigned integer"); \ static_assert((key) >= (1ull << 56), "key must span all 8 bytes"); \ using char_type = ay::char_type; \ constexpr auto n = sizeof(data)/sizeof(data[0]); \ constexpr auto obfuscator = ay::make_obfuscator(data); \ thread_local auto obfuscated_data = ay::obfuscated_data(obfuscator); \ return obfuscated_data; \ }()