为什么使用WinInet.h库发送C++请求总是返回”HMAC签名不匹配”?

huangapple go评论73阅读模式
英文:

Why C++ sending request with WinInet.h library always returned "HMAC signature does not match"?

问题

I used to write Python codes to send requests and now trying to switch to C++.
我以前用Python编写代码发送请求,现在正在尝试切换到C++。

I’m new to sending HTTPS request with WinInet.h library in C++ code, and seeking assistance regarding the usage of the WinInet.h library for handling HTTPS requests with headers of X-Ca-Signature.
我对在C++代码中使用WinInet.h库发送HTTPS请求还不熟悉,并寻求关于如何使用WinInet.h库处理具有X-Ca-Signature头的HTTPS请求的帮助。

The “headers” settings are the same for both Python and C++ code.
Python code could run perfectly, but C++ could not.
The compiled C++ code would always return: "HMAC signature does not match", which seems that C++ with "wininet.h" library didn't handle them correctly.
“headers”设置对于Python和C++代码是相同的。
Python代码可以完美运行,但C++不能。
编译后的C++代码总是返回:“HMAC签名不匹配”,似乎C++与“wininet.h”库没有正确处理它们。

The original Python code is:
原始的Python代码如下:

(Note: all the values of 'X-Ca-Key', 'X-Ca-Signature', 'X-Ca-Nonce', 'X-Access-Token' have been calculated correctly, and are omitted in the following codes)
(注:所有'X-Ca-Key','X-Ca-Signature','X-Ca-Nonce','X-Access-Token'的值都已经正确计算,并在以下代码中省略了)

[Python代码]

And the equivalent C++ code with “wininet” library is:
等价的带有“wininet”库的C++代码如下:

[C++代码]

I have been struggling to try various approaches provided by ChatGPT, and spent considerable time debugging. Unfortunately, I haven't been able to find a solution.
我一直在努力尝试ChatGPT提供的各种方法,并花费了大量时间进行调试。不幸的是,我还没有找到解决方案。

I tried adding the following statements to retrieve the headers information:
我尝试添加以下语句来检索头信息:

[检索头信息的代码]

The output result showed:
输出结果如下:

[输出结果]

I compared that all the contents of the above "......" are exactly the same as those in the original code.
我比较了上述的所有内容的“......”部分与原始代码中的内容完全相同。

Why not using CURL library?
为什么不使用CURL库?

As a matter of fact, I have already tested another C++ code with CURL library.
事实上,我已经测试了另一个使用CURL库的C++代码。
CURL is able to send GET and POST requests perfectly with the same headers as those in Python code.
CURL能够完美地发送GET和POST请求,使用的头部与Python代码中的相同。

The disadvantage of CURL is that the compiled executable file runs dependent with "libcurl-x64.dll" which may not be exist in every user's Windows system.
CURL的缺点是编译后的可执行文件依赖于“libcurl-x64.dll”,这可能在每个用户的Windows系统中都不存在。

In comparison, the Windows has built-in "wininet.dll" dynamic library, so that I can take full advantage of the "WinInet".
相比之下,Windows内置了“wininet.dll”动态库,因此我可以充分利用“WinInet”。

I suspect there might be some limitations or specific requirements when using wininet.h library for requests with X-Ca-Signature headers, but I couldn't find any relevant information or examples in the documentation.
我怀疑在使用wininet.h库处理具有X-Ca-Signature头的请求时可能存在一些限制或特定要求,但我在文档中找不到任何相关信息或示例。

If anyone has experience with wininet.h or has encountered a similar issue with X-Ca-Signature headers in HTTPS requests, I would greatly appreciate your insights, suggestions, or any examples that could help me overcome this challenge.
如果有人有wininet.h的经验,或在HTTPS请求中遇到过类似的X-Ca-Signature头问题,我将非常感激您的见解、建议或任何示例,可以帮助我克服这个问题。

英文:

I used to write Python codes to send requests and now trying to switch to C++.
I’m new to sending HTTPS request with WinInet.h library in C++ code, and seeking assistance regarding the usage of the WinInet.h library for handling HTTPS requests with headers of X-Ca-Signature.

The “headers” settings are the same for both Python and C++ code.
Python code could run perfectly, but C++ could not.
The compiled C++ code would always returned: "HMAC signature does not match", which seems that C++ with “wininet.h” library didn’t handle them correctly.

The original Python code is:
(note: all the values of 'X-Ca-Key', 'X-Ca-Signature', 'X-Ca-Nonce', 'X-Access-Token' have been calculated correctly, and are omitted in the following codes)

import requests

url = "https://......"

headers = {
  'User-agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64)',
  'Content-Type': 'application/json;charset=UTF-8',
  'X-Ca-Signature-Headers': 'x-ca-key,x-ca-nonce',
  'X-Ca-Key': '......',
  'X-Ca-Signature': '......'
  'X-Ca-Nonce': '......',
  'X-Access-Token': '......',
}

response = requests.get(url, headers=headers)

print(response.text)

And the equivalent C++ code with “wininet” library is:

#include <iostream>
#include <string>
#include <wininet.h>
using namespace std;
#pragma comment(lib, "wininet.lib")

void send_request(const string& url, const string& headers, string* htmltext) {
    HINTERNET Session = InternetOpenA("Mozilla/5.0 (Windows NT 10.0; Win64; x64)", INTERNET_OPEN_TYPE_DIRECT, nullptr, nullptr, 0);
    if (!Session) {
        *htmltext = "InternetOpenA Error";
        return;
    }

    HINTERNET Connect = InternetOpenUrlA(Session, url.c_str(), headers.c_str(), headers.length(), INTERNET_FLAG_RELOAD, 0);
    if (!Connect) {
        *htmltext = "InternetOpenUrlA Error";
        InternetCloseHandle(Session);
        return;
    }

    DWORD BytesRead;
    string response;
    char buffer[4096];
    while (InternetReadFile(Connect, buffer, sizeof(buffer), &BytesRead) && BytesRead > 0) {
        response.append(buffer, BytesRead);
    }

    *htmltext = response;

    InternetCloseHandle(Connect);
    InternetCloseHandle(Session);
}

int main() {
    string url = "https://......";
    string headers = "User-agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64)\r\n"
                     "Content-Type: application/json;charset=UTF-8\r\n"
                     "X-Ca-Signature-Headers: x-ca-key,x-ca-nonce\r\n"
                     "X-Ca-Key: ......\r\n"
                     "X-Ca-Signature: ......\r\n"
                     "X-Ca-Nonce: ......\r\n"
                     "X-Access-Token: ......\r\n\r\n";
    string htmltext;
    send_request(url, headers, &htmltext);
    cout << htmltext << endl;
    return 0;
}

I have been struggling to try various approaches provided by ChatGPT, and spent considerable time debugging. Unfortunately, I haven't been able to find a solution.

I tried adding the following statements to retrieve the headers information:

    DWORD header_buffer_size = 4096;
    char headers_buffer[header_buffer_size];
    if (HttpQueryInfo(Connect, HTTP_QUERY_RAW_HEADERS_CRLF|HTTP_QUERY_FLAG_REQUEST_HEADERS, headers_buffer, &header_buffer_size, NULL)) {
        cout << "Headers after sending request:\n" << headers_buffer << endl;
    } else {
        cout << "Failed retrieval of headers" << endl;
    }

The output result showed:

Headers after sending request:
GET /...... HTTP/1.1
User-agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64)
Content-Type: application/json;charset=UTF-8
X-Ca-Nonce: ......
X-Access-Token: ......
X-Ca-Key: ......
X-Ca-Signature-Headers: x-ca-key,x-ca-nonce
X-Ca-Signature: ......
Host: ......
Cache-Control: no-cache
Cookie: ......

I compared that all the contents of the above "......" are exactly the same as those in the original code.

Why not using CURL library?

As a matter of fact, I have already tested another C++ code with CURL library.
CURL is able to send GET and POST requests perfectly with the same headers as those in Python code.

The disadvantage of CURL is that the compiled executable file runs dependent with “libcurl-x64.dll” which may not be exist in every user’s Windows system.

In comparison, the Windows has built-in “wininet.dll” dynamic library, so that I can take full advantage of the “WinInet”.

I suspect there might be some limitations or specific requirements when using wininet.h library for requests with X-Ca-Signature headers, but I couldn't find any relevant information or examples in the documentation.

If anyone has experience with wininet.h or has encountered a similar issue with X-Ca-Signature headers in HTTPS requests, I would greatly appreciate your insights, suggestions, or any examples that could help me overcome this challenge.

答案1

得分: 1

谢谢您的回复!

通过调试客户端发送到服务器的标头,我意识到“WinInet.h”库默认情况下不会自动添加必要的标头组件,例如“accept”,“accept-encoding”,“accept-language”,这与Python的“requests”函数不同。

我不得不手动添加以下语句到“headers”字符串中:

"Accept: */*\r\n"
"Accept-Encoding: gzip, deflate, br\r\n"
"Accept-Language: zh-CN,zh;q=0.9,zh-TW;q=0.8,en;q=0.7\r\n"

最终,我的C++代码与“wininet.h”库能够成功发送GET和POST请求!我对编译后的可执行文件如此小感到满意。

话虽如此,对于Python的“requests”函数,不用担心默认标头设置,但对于C++,我们必须从头开始。

再次感谢您的建议。我认为这个话题可以关闭。

英文:

thank you for your replies!

By debugging the headers that the client sent to the server, I realized that the WinInet.h library did not automatically add the necessary header components such as "accept", "accept-encoding", "accept-language" by default, which behaves differently from the that of Python's requests functions.

I had to manually add the headers with the following statements to the "headers" string:

"Accept: */*\r\n"
"Accept-Encoding: gzip, deflate, br\r\n"
"Accept-Language: zh-CN,zh;q=0.9,zh-TW;q=0.8,en;q=0.7\r\n"

Finally my C++ code with "wininet.h" library is able to send both GET and POST requests successfully! I'm quite satisfied that the compiled executable file is so tiny.

That said, in case of Python's requests function, no worries about the default header settings, but when it comes to C++, we have to start from scratch.

Thanks again for your ideas. I think this topic can be closed.

huangapple
  • 本文由 发表于 2023年6月15日 15:07:55
  • 转载请务必保留本文链接:https://go.coder-hub.com/76479941.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定