Skip to content

Commit 3d1d4d8

Browse files
committed
security: add strict signature header validation and secondary req() verification
1 parent 0aaac9b commit 3d1d4d8

File tree

1 file changed

+45
-0
lines changed

1 file changed

+45
-0
lines changed

auth.cpp

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -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

Comments
 (0)