为什么我的签名与亚马逊的例子不同?(C++/REST/授权签名版本4)

Why is my signature different from Amazons example? (C++/REST/Authorization Signature Version 4)

本文关键字:C++ REST 版本 授权 亚马逊 我的 为什么      更新时间:2023-10-16

我正在遵循本页上给出的示例,最终使用此处给出的详细信息获得了正确的签名。

我的问题是我正确地获得了签名ced6826de92d2bdeed8f846f0bf508e8559e98e4b0199114b84c54174deb456c,但是,只要我使用相同的方法并更改本页get示例的变量,它就会给我签名c2eb7ddb12cb2c46489fdf97947e68b24c3716而不是f0e8bdb87c964420e857bd35b5d6ed310bd44f0170aba48dd91039c6036bdb41

这是使用openSSL进行HMAC和SHA256哈希的C++代码。

测试功能

void Test3()
{
	std::string date = std::string("20130524");
	std::string region = std::string("us-east-1");
	std::string service = std::string("s3");
	std::string request = std::string("aws4_request");
	std::string key = std::string("AWS4wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY");
	unsigned char* signingKey = EncodeHMACSHA256_2(EncodeHMACSHA256_2(EncodeHMACSHA256_2(EncodeHMACSHA256_2((unsigned char*)key.c_str(), &date), &region), &service), &request);
	std::string stringToSign = std::string();
	stringToSign.append("AWS4-HMAC-SHA256n");
	stringToSign.append("20130524T000000Zn");
	stringToSign.append("20130524/us-east-1/s3/aws4_requestn");
	stringToSign.append("7344ae5b7ee6c3e7e6b0fe0640412a37625d1fbfff95c48bbb2dc43964946972");
	// Create signature
	unsigned char* signature = EncodeHMACSHA256_2(signingKey, &stringToSign);
	// to hex
	std::string sigHex = ToHex(signature);
}

HMAC功能

unsigned char* EncodeHMACSHA256_2(unsigned char* key, std::string* value)
{
	const unsigned char* dataToHash = (unsigned char*)value->c_str();
	// Initialise HMAC
	HMAC_CTX HMAC;
	unsigned int hmaclength = 64;		// Length of the resulting SHA256 hash
	unsigned char* hmachash = (unsigned char*)malloc(sizeof(char) * hmaclength);
	memset(hmachash, 0, hmaclength);
	// Digest the key and message using SHA256
	HMAC_CTX_init(&HMAC);
	HMAC_Init(&HMAC, key, strlen((char*)key), EVP_sha256());
	HMAC_Update(&HMAC, dataToHash, strlen((char*)dataToHash));
	HMAC_Final(&HMAC, hmachash, &hmaclength);
	HMAC_CTX_cleanup(&HMAC);
	return hmachash;
}

十六进制函数

std::string ToHex(unsigned char* value)
{
	int len = strlen((char*)value);
	std::stringstream stream;
	for (int i = 0; i < len; i++)
	{
		char tmpStr[3] = { 0 };
		int res = sprintf(tmpStr, "%02x", value[i]);
		stream << tmpStr;
	}
	return stream.str();
}

HMAC函数导致了这个问题,我将无符号的char*转换为char*,并取该长度,一旦它达到零,就会结束,从而给出不同的长度。将函数更改为包含键和值的长度。

HMAC长度从64更改为32,并将32传递到键长度的函数中。

要在亚马逊网站上给出的例子中警告其他人,请注意,要签署日期的字符串不是ISO格式的,它与您在日期标题中传递的日期和时间相同,即周一、10月6日等。

如果您使用C++11,我们也可以使用vector。使用vector的好处是不必跟踪内存的释放。

我在这里有一个相同的实现-在C++(DynamoDB)中的HMAC SHA256