DonoWall
DonoWall

Reputation: 1

any wrong I done for using Openssl for calculating HMAC_SHA1 hash value?

 int  computeHMACSHA1Hash(const char * unhashedcstr, char * hashedcstr, const char * key, int returncode)
 {

string  hashed;

size_t unhashlength = strlen(unhashedcstr);

char * nonconstunhashcstr = new char[unhashlength];

strcpy_s(nonconstunhashcstr, unhashlength + 1, unhashedcstr);

unsigned char* pixels = reinterpret_cast<unsigned char*>(nonconstunhashcstr);

returncode = 0;
HMAC_CTX* context = HMAC_CTX_new();

size_t unhashedstrlength = sizeof(unhashedcstr);

if (context != NULL)
{
    if (HMAC_Init_ex(context, key, strlen(key), EVP_sha1(), NULL))
    {
        if (HMAC_Update(context, pixels, unhashedstrlength))
        {
            unsigned char hash[EVP_MAX_MD_SIZE];
            unsigned int lengthOfHash = 0;

            if (HMAC_Final(context, hash, &lengthOfHash))
            {
                std::stringstream ss;
                for (unsigned int i = 0; i < lengthOfHash; ++i)
                {
                    ss << std::hex << std::setw(2) << std::setfill('0') << (int)hash[i];
                }

                hashed = ss.str();
                size_t outputSize = hashed.length() + 1; // +1 for null terminator
                strcpy_s(hashedcstr, outputSize, hashed.c_str());

                returncode = 0;
            }
            else
            {
                returncode = 7;
            }
        }
        else
        {
            returncode = 6;
        }
    }
    else
    {
        returncode = 5;
    }

    HMAC_CTX_free(context);
}
else
{
    returncode = 4;
}

return returncode;

}

int main()
{
     const char * unhashedcstr = "a=services&l=v1&p=open&k=SD58292829&i=20200918125249803&n=2124&t=1600404769&f={\"invoiceCode\": \"11111\",\"invoiceNo\": \"2222\",\"inTaxAmount\": \"\",\"exTaxAmount\": \"\"}";
     char * hashedcstr = new char[100];
     int returncode = 0;
     const char * key = "SD886A11B0EE428F";

     int result = computeHMACSHA1Hash(unhashedcstr, hashedcstr, key, returncode);
     return 0;
}

I tried the code above to calculating the HMAC SHA1 hash value for a content, but compared the results on https://www.freeformatter.com/hmac-generator.html#before-output it looks like I didn't do it right. I'm not sure what I have done wrong though. Any help would be appreciated.

It turned out the result was "d916b4c2d277319bbf18076c158f0cbcf6c3bc57", while on the website https://www.freeformatter.com/hmac-generator.html#before-output, the result was "71482b292f2b2a47b3eca6dad5e7350566d60963". Even when I tried using the string "a=services&l=v1&p=open&k=SD58292829&i=20200918125249803&n=2124&t=1600404769&f={"invoiceCode": "11111","invoiceNo": "2222","inTaxAmount": "","exTaxAmount": ""}" which removed the escape characters, the result was "09be98b6129c149e685ed57a1d19651a602cda0d". It didn't match the correct one.

Is there anything wrong with my code?

Upvotes: 0

Views: 141

Answers (1)

heap underrun
heap underrun

Reputation: 2509

Your hash is calculated over the bytes a=se, which are the first four bytes of the whole input string. Thus, you get d916b4c2d277319bbf18076c158f0cbcf6c3bc57 instead of the 09be98b6129c149e685ed57a1d19651a602cda0d that would correspond to the whole string.

The reason is this:

size_t unhashedstrlength = sizeof(unhashedcstr);

Here, sizeof(unhashedcstr) is the size of the unhashedcstr pointer itself (which is of type const char*), not the size of the null-terminated C-style string this unhashedcstr pointer is pointing to. You are compiling a 32-bit program, so the size of a pointer is 4 bytes. Thus, unhashedstrlength is 4.

To get the length of the C-style string, you can do this instead:

size_t unhashedstrlength = strlen(unhashedcstr);

But just as a comment, in modern C++, you should avoid using raw pointers (such as const char*, char*, unsigned char*), C functions (like strlen(), strcpy_s()) and manual memory management (new / delete and new[] / delete[]). You should prefer to use std::string and/or std::vector<unsigned char> instead, wherever possible. When you need to pass a buffer's address to an API function, you can use std::string::data(), std::vector::data(), or more generally, std::data().

By the way, you currently leak memory: you dynamically allocate buffers using new[], but you never deallocate those (using delete[]). So that memory is released by the OS only after the program exits. This is called a memory leak.

Upvotes: 1

Related Questions