C++中的HMAC SHA256(DynamoDB)

Mik*_*ard 3 c++ openssl hmac amazon-web-services amazon-dynamodb

我正在尝试通过REST Web API连接到DynamoDB,它要求我使用HMAC-SHA256生成签名.我有SHA-256工作,但我似乎无法让HMAC工作,这里是C++代码(使用OpenSSL)

string hmac(string key, string msg)
{
    unsigned char hash[32];

    HMAC_CTX hmac;
    HMAC_CTX_init(&hmac);
    HMAC_Init_ex(&hmac, &key[0], key.length(), EVP_sha256(), NULL);
    HMAC_Update(&hmac, (unsigned char*) &msg[0], msg.length());
    unsigned int len = 32;
    HMAC_Final(&hmac, hash, &len);
    HMAC_CTX_cleanup(&hmac);

    stringstream ss;
    for (int i = 0; i < len; i++)
    {   
        ss << hex  <<  ( unsigned int )hash[i];
    }

    return ss.str();
}
Run Code Online (Sandbox Code Playgroud)

这是对hmac的调用

    /*********************************************CALCULATE SIGNATURE****************************************************************/

string AWS4 = "AWS4" + secretKey;

string Kdate = hmac(AWS4.data(), dateStamp);
string Kregion = hmac(Kdate.data(), region);
string Kservice = hmac(Kregion.data(), service);
string signingkey = hmac(Kservice.data(), "aws4_request");

string signature = hmac(signingkey.data(), stringToSign);

string authoritzationHeader = algorithm + " Credential=" + accessKey + "/" + credential_scope + ", SignedHeaders=" + signedHeaders + ", Signature=" + signature;
Run Code Online (Sandbox Code Playgroud)

这是我基于它的Python代码:

def sign(key, msg):
    return hmac.new(key, msg.encode("utf-8"), hashlib.sha256).digest()

def getSignatureKey(key, date_stamp, regionName, serviceName):
    kDate    = sign(('AWS4' + key).encode('utf-8'), date_stamp)
    kRegion  = sign(kDate, regionName)
    kService = sign(kRegion, serviceName)
    kSigning = sign(kService, 'aws4_request')

    print 'Kdate: ' + kDate
    print 'Kregion: ' + kRegion 
    print 'Kservice: ' + kService

    return kSigning
Run Code Online (Sandbox Code Playgroud)

给定相同的值,它们会产生不同的结果.任何人都可以帮助我为什么这是?谢谢.

Mik*_*ard 10

问题是DynamoDB以两种不同的方式计算hmac.第一个返回字符串表示,第二个返回十六进制表示

十六进制实现

string hmacHex(string key, string msg)
{
    unsigned char hash[32];

    HMAC_CTX hmac;
    HMAC_CTX_init(&hmac);
    HMAC_Init_ex(&hmac, &key[0], key.length(), EVP_sha256(), NULL);
    HMAC_Update(&hmac, (unsigned char*)&msg[0], msg.length());
    unsigned int len = 32;
    HMAC_Final(&hmac, hash, &len);
    HMAC_CTX_cleanup(&hmac);

    std::stringstream ss;
    ss << std::hex << std::setfill('0');
    for (int i = 0; i < len; i++)
    {   
        ss << std::hex << std::setw(2)  << (unsigned int)hash[i];
    }

    return (ss.str());
}
Run Code Online (Sandbox Code Playgroud)

字符串实现

string hmac(string key, string msg)
{
    unsigned char hash[32];

    HMAC_CTX hmac;
    HMAC_CTX_init(&hmac);
    HMAC_Init_ex(&hmac, &key[0], key.length(), EVP_sha256(), NULL);
    HMAC_Update(&hmac, ( unsigned char* )&msg[0], msg.length());
    unsigned int len = 32;
    HMAC_Final(&hmac, hash, &len);
    HMAC_CTX_cleanup(&hmac);

    std::stringstream ss;
    ss << std::setfill('0');
    for (int i = 0; i < len; i++)
    {
        ss  << hash[i];
    }

    return (ss.str());
}
Run Code Online (Sandbox Code Playgroud)

亚马逊对所有日期,区域,服务和签名密钥使用十六进制实现.字符串实现仅用于签名