@@ -3561,6 +3561,21 @@ std::string KeyAuth::api::req(std::string data, const std::string& url) {
35613561 error (XorStr (" missing signature headers." ));
35623562 }
35633563
3564+ if (signature.size () != 128 || !std::all_of (signature.begin (), signature.end (),
3565+ [](unsigned char c) { return std::isxdigit (c) != 0 ; })) {
3566+ if (req_headers) curl_slist_free_all (req_headers);
3567+ curl_easy_cleanup (curl);
3568+ error (XorStr (" invalid signature header format." ));
3569+ }
3570+
3571+ if (signatureTimestamp.size () < 10 || signatureTimestamp.size () > 13 ||
3572+ !std::all_of (signatureTimestamp.begin (), signatureTimestamp.end (),
3573+ [](unsigned char c) { return c >= ' 0' && c <= ' 9' ; })) {
3574+ if (req_headers) curl_slist_free_all (req_headers);
3575+ curl_easy_cleanup (curl);
3576+ error (XorStr (" invalid signature timestamp header format." ));
3577+ }
3578+
35643579 // Enforce cryptographic payload verification on every request path.
35653580 const int verify_result = VerifyPayload (signature, signatureTimestamp, to_return);
35663581 if ((verify_result & 0xFFFF ) != ((42 ^ 0xA5A5 ) & 0xFFFF )) {
@@ -3569,6 +3584,36 @@ std::string KeyAuth::api::req(std::string data, const std::string& url) {
35693584 error (XorStr (" payload verification marker mismatch." ));
35703585 }
35713586
3587+ // Independent verification path so hooking one verifier is insufficient.
3588+ if (sodium_init () < 0 ) {
3589+ if (req_headers) curl_slist_free_all (req_headers);
3590+ curl_easy_cleanup (curl);
3591+ error (XorStr (" libsodium init failed in request guard." ));
3592+ }
3593+
3594+ unsigned char sig_guard[64 ] = { 0 };
3595+ unsigned char pk_guard[32 ] = { 0 };
3596+ if (sodium_hex2bin (sig_guard, sizeof (sig_guard), signature.c_str (), signature.size (), nullptr , nullptr , nullptr ) != 0 ) {
3597+ if (req_headers) curl_slist_free_all (req_headers);
3598+ curl_easy_cleanup (curl);
3599+ error (XorStr (" signature decode failed in request guard." ));
3600+ }
3601+ const std::string pubkey_hex_guard = get_public_key_hex ();
3602+ if (sodium_hex2bin (pk_guard, sizeof (pk_guard), pubkey_hex_guard.c_str (), pubkey_hex_guard.size (), nullptr , nullptr , nullptr ) != 0 ) {
3603+ if (req_headers) curl_slist_free_all (req_headers);
3604+ curl_easy_cleanup (curl);
3605+ error (XorStr (" public key decode failed in request guard." ));
3606+ }
3607+ const std::string signed_message_guard = signatureTimestamp + to_return;
3608+ if (crypto_sign_ed25519_verify_detached (sig_guard,
3609+ reinterpret_cast <const unsigned char *>(signed_message_guard.data ()),
3610+ signed_message_guard.size (),
3611+ pk_guard) != 0 ) {
3612+ if (req_headers) curl_slist_free_all (req_headers);
3613+ curl_easy_cleanup (curl);
3614+ error (XorStr (" signature verify failed in request guard." ));
3615+ }
3616+
35723617 char * effective_url = nullptr ;
35733618 if (curl_easy_getinfo (curl, CURLINFO_EFFECTIVE_URL, &effective_url) == CURLE_OK && effective_url) {
35743619 if (!is_https_url (effective_url)) {
0 commit comments