@@ -137,7 +137,22 @@ void cleanUpSeedData(const std::string& seed);
137137std::string signature;
138138std::string signatureTimestamp;
139139bool initialized;
140- std::string API_PUBLIC_KEY = " 5586b4bc69c7a4b487e4563a4cd96afd39140f919bd31cea7d1c6a1e8439422b" ;
140+ static constexpr uint8_t k_pubkey_xor1 = 0x5A ;
141+ static constexpr uint8_t k_pubkey_xor2 = 0xA5 ;
142+ static constexpr uint64_t k_pubkey_fnv1a = 0x7553f24ca052d4b1ULL ;
143+ static const uint8_t k_pubkey_obf1[64 ] = {
144+ 0x6f , 0x6f , 0x62 , 0x6c , 0x38 , 0x6e , 0x38 , 0x39 , 0x6c , 0x63 , 0x39 , 0x6d , 0x3b , 0x6e , 0x38 , 0x6e ,
145+ 0x62 , 0x6d , 0x3f , 0x6e , 0x6f , 0x6c , 0x69 , 0x3b , 0x6e , 0x39 , 0x3e , 0x63 , 0x6c , 0x3b , 0x3c , 0x3e ,
146+ 0x69 , 0x63 , 0x6b , 0x6e , 0x6a , 0x3c , 0x63 , 0x6b , 0x63 , 0x38 , 0x3e , 0x69 , 0x6b , 0x39 , 0x3f , 0x3b ,
147+ 0x6d , 0x3e , 0x6b , 0x39 , 0x6c , 0x3b , 0x6b , 0x3f , 0x62 , 0x6e , 0x69 , 0x63 , 0x6e , 0x68 , 0x68 , 0x38
148+ };
149+ static const uint8_t k_pubkey_obf2[64 ] = {
150+ 0x90 , 0x90 , 0x9d , 0x93 , 0xc7 , 0x91 , 0xc7 , 0xc6 , 0x93 , 0x9c , 0xc6 , 0x92 , 0xc4 , 0x91 , 0xc7 , 0x91 ,
151+ 0x9d , 0x92 , 0xc0 , 0x91 , 0x90 , 0x93 , 0x96 , 0xc4 , 0x91 , 0xc6 , 0xc1 , 0x9c , 0x93 , 0xc4 , 0xc3 , 0xc1 ,
152+ 0x96 , 0x9c , 0x94 , 0x91 , 0x95 , 0xc3 , 0x9c , 0x94 , 0x9c , 0xc7 , 0xc1 , 0x96 , 0x94 , 0xc6 , 0xc0 , 0xc4 ,
153+ 0x92 , 0xc1 , 0x94 , 0xc6 , 0x93 , 0xc4 , 0x94 , 0xc0 , 0x9d , 0x91 , 0x96 , 0x9c , 0x91 , 0x97 , 0x97 , 0xc7
154+ };
155+ static std::atomic<uint64_t > pubkey_hash_seen{ 0 };
141156bool KeyAuth::api::debug = false ;
142157std::atomic<bool > LoggedIn (false );
143158std::atomic<long long > last_integrity_check{ 0 };
@@ -188,6 +203,59 @@ static inline void securewipe(std::string& value) noexcept
188203 secure_zero (value);
189204}
190205
206+ static uint64_t fnv1a64_bytes (const uint8_t * data, size_t len)
207+ {
208+ uint64_t h = 0xcbf29ce484222325ULL ;
209+ for (size_t i = 0 ; i < len; ++i) {
210+ h ^= static_cast <uint64_t >(data[i]);
211+ h *= 0x100000001b3ULL ;
212+ }
213+ return h;
214+ }
215+
216+ static std::string decode_pubkey_hex (const uint8_t * obf, size_t len, uint8_t key)
217+ {
218+ std::string out;
219+ out.resize (len);
220+ for (size_t i = 0 ; i < len; ++i) {
221+ out[i] = static_cast <char >(obf[i] ^ key);
222+ }
223+ return out;
224+ }
225+
226+ static bool pubkey_memory_protect_ok ()
227+ {
228+ MEMORY_BASIC_INFORMATION mbi{};
229+ if (!VirtualQuery (k_pubkey_obf1, &mbi, sizeof (mbi)))
230+ return false ;
231+ const DWORD p = mbi.Protect ;
232+ if (p & PAGE_GUARD)
233+ return false ;
234+ if ((p & PAGE_READWRITE) || (p & PAGE_WRITECOPY) ||
235+ (p & PAGE_EXECUTE_READWRITE) || (p & PAGE_EXECUTE_WRITECOPY)) {
236+ return false ;
237+ }
238+ return true ;
239+ }
240+
241+ static std::string get_public_key_hex ()
242+ {
243+ if (!pubkey_memory_protect_ok ()) {
244+ error (XorStr (" public key memory protection tampered." ));
245+ }
246+ std::string a = decode_pubkey_hex (k_pubkey_obf1, sizeof (k_pubkey_obf1), k_pubkey_xor1);
247+ std::string b = decode_pubkey_hex (k_pubkey_obf2, sizeof (k_pubkey_obf2), k_pubkey_xor2);
248+ if (a != b) {
249+ error (XorStr (" public key mismatch detected." ));
250+ }
251+ const uint64_t h = fnv1a64_bytes (reinterpret_cast <const uint8_t *>(a.data ()), a.size ());
252+ pubkey_hash_seen.store (h, std::memory_order_relaxed);
253+ if (h != k_pubkey_fnv1a) {
254+ error (XorStr (" public key integrity failed." ));
255+ }
256+ return a;
257+ }
258+
191259struct ScopeWipe final {
192260 std::string* value;
193261 explicit ScopeWipe (std::string& v) noexcept : value(&v) {}
@@ -215,6 +283,7 @@ void KeyAuth::api::init()
215283 std::thread (runChecks).detach ();
216284 snapshot_prologues ();
217285 snapshot_checkinit ();
286+ (void )get_public_key_hex ();
218287 seed = generate_random_number ();
219288 std::atexit ([]() { cleanUpSeedData (seed); });
220289
@@ -1965,7 +2034,8 @@ int VerifyPayload(std::string signature, std::string timestamp, std::string body
19652034 exit (5 );
19662035 }
19672036
1968- if (sodium_hex2bin (pk, sizeof (pk), API_PUBLIC_KEY.c_str (), API_PUBLIC_KEY.length (), NULL , NULL , NULL ) != 0 ) {
2037+ const std::string pubkey_hex = get_public_key_hex ();
2038+ if (sodium_hex2bin (pk, sizeof (pk), pubkey_hex.c_str (), pubkey_hex.length (), NULL , NULL , NULL ) != 0 ) {
19692039 std::cerr << " [ERROR] Failed to parse public key hex.\n " ;
19702040 MessageBoxA (0 , " Signature verification failed (invalid public key)" , " KeyAuth" , MB_ICONERROR);
19712041 exit (6 );
@@ -1975,7 +2045,7 @@ int VerifyPayload(std::string signature, std::string timestamp, std::string body
19752045 std::cout << "[DEBUG] Signature: " << signature << std::endl;
19762046 std::cout << "[DEBUG] Body: " << body << std::endl;
19772047 std::cout << "[DEBUG] Message (timestamp + body): " << message << std::endl;
1978- std::cout << "[DEBUG] Public Key: " << API_PUBLIC_KEY << std::endl;*/
2048+ std::cout << "[DEBUG] Public Key: " << pubkey_hex << std::endl;*/
19792049
19802050 if (crypto_sign_ed25519_verify_detached (sig,
19812051 reinterpret_cast <const unsigned char *>(message.c_str ()),
0 commit comments