Ducky
Ducky

Reputation: 21

Convert Node JS HMAC to C#

I have been attempting to convert an HMAC middleware code snip to C#. The Node JS code is very simple.

 const hash = crypto
.createHmac('sha256', 'SHA-Key')
.update(JSON.stringify(req.body))
.digest('hex');

if (hash === req.header('X-HMAC-Sha-256')) {
    next();
} else {
    res.send(401, 'Not authorized.');
}

My C# code

    public string CalculateSHA256Hash(byte[] key, string requestContent, string senderHash)
    {   
        string hexHash = "";
        // Initialize the keyed hash object.
        using (HMACSHA256 hmac = new HMACSHA256(key))
        {
            byte[] requestByteArray = Encoding.UTF8.GetBytes(requestContent);

            // Create a FileStream for the source file.
            using (MemoryStream inStream = new MemoryStream(requestByteArray))
            {
                // Read in the storedHash.
                inStream.Read(requestByteArray, 0, requestByteArray.Length);
                // Compute the hash of the remaining contents of the file.
                // The stream is properly positioned at the beginning of the content,
                // immediately after the stored hash value.
                byte[] computedHash = hmac.ComputeHash(inStream);
                hexHash = Convert.ToHexString(computedHash);
            }
        }

        return hexHash;
     }

When I run the code I never get the same result as the senders HMAC hash. Is it something to do with the Digest Hex in node.js vs my convert toHexString?

Upvotes: 0

Views: 515

Answers (1)

Ducky
Ducky

Reputation: 21

So I needed to dig into exactly what the node.js code was accomplishing for this HMAC hash. I found that once I understood what the json.stringify() was doing this became trivial to implement.

    public string CalculateSHA256Hash(byte[] key, string requestContent)
    {
        string hexHash = "";
        try
        {
            // Initialize the keyed hash object.
            using (HMACSHA256 hmac = new HMACSHA256(key))
            {
                byte[] requestByteArray = Encoding.UTF8.GetBytes(requestContent);

                // Create a FileStream for the source request body.
                using (MemoryStream inStream = new MemoryStream(requestByteArray))
                {
                    byte[] computedHash = hmac.ComputeHash(inStream);
                    hexHash = Convert.ToHexString(computedHash).ToLower();
                }
            }
        }
        catch (Exception e)
        {
            throw;
        }
        return hexHash;
    }

I used the following to get the equivalent of json.stringify()

     //Stringify
     strBody = strBody.Replace(" ", "");
     strBody = strBody.Replace(Environment.NewLine, "");

Upvotes: 1

Related Questions