6

I am trying to integrate with a 3rd party API that requires my request body and some variables to be encrypted and uses an HMAC Signature for authorization. They've provided me with a sample javascript code:

function generateHMACSignature(partnerID, partnerSecret,
httpMethod, requestURL, contentType, requestBody, timestamp) {
var requestPath = getPath(requestURL);
var queryString = getQueryString(requestURL);
if (httpMethod == 'GET' || !requestBody) {
requestBody = '';
}
var hashedPayload =
CryptoJS.enc.Base64.stringify(CryptoJS.SHA256(requestBody));
var requestData = [[httpMethod, contentType, timestamp,
requestPath, hashedPayload].join('\n'), '\n'].join('');
var hmacDigest =
CryptoJS.enc.Base64.stringify(CryptoJS.HmacSHA256(requestData,
partnerSecret));
return hmacDigest;
}

function getPath(url) {
var pathRegex = /.+?\:\/\/.+?(\/.+?)(?:#|\?|$)/;
var result = url.match(pathRegex);
if(!result){
pathRegex = /\/.*/;
result = url.match(pathRegex);
return result && result.length == 1 ? result[0] : '';
}
return result && result.length > 1 ? result[1] : '';
}

function getQueryString(url) {
var arrSplit = url.split('?');
return arrSplit.length > 1 ? url.substring(url.indexOf('?')+1) : '';
}

Searched the web for codes in c# how to todo sha256 and HMAC sigs:

 public static String GetHMAC(String text, String key)
        {
            var enc = Encoding.Default;
            HMACSHA256 hmac = new HMACSHA256(enc.GetBytes(key));
            hmac.Initialize();

            byte[] buffer = enc.GetBytes(text);
            return BitConverter.ToString(hmac.ComputeHash(buffer)).Replace("-", "").ToLower();
        }


        static string ComputeSha256Hash(string rawData)
        {
            // Create a SHA256   
            using (SHA256 sha256Hash = SHA256.Create())
            {
                // ComputeHash - returns byte array  
                byte[] bytes = sha256Hash.ComputeHash(Encoding.UTF8.GetBytes(rawData));

                // Convert byte array to a string   
                StringBuilder builder = new StringBuilder();
                for (int i = 0; i < bytes.Length; i++)
                {
                    builder.Append(bytes[i].ToString("x2"));
                }
                return builder.ToString();
            }
        }

        public static string Base64Encode(string plainText)
        {
            var plainTextBytes = System.Text.Encoding.UTF8.GetBytes(plainText);
            return System.Convert.ToBase64String(plainTextBytes);
        }

The results from the code that hey provided differs from the coverted code. Is there something wrong with the code I got?

In short what's the correct way to do: CryptoJS.SHA256(); and CryptoJS.HmacSHA256(); in c#?

2
  • You might want Encoding.UTF8 instead of default to match JavaScript
    – bartonjs
    Commented Aug 9, 2019 at 4:35
  • Perhaps you can show test inputs and the resultant output from both C# and Javascript? Commented Aug 9, 2019 at 4:37

1 Answer 1

14

for the sha256 and HMAC part, you could do this :

private string GetHMAC(string text, string key)
{
    key = key ?? "";

    using (var hmacsha256 = new HMACSHA256(Encoding.UTF8.GetBytes(key)))
    {
        var hash = hmacsha256.ComputeHash(Encoding.UTF8.GetBytes(text));
        return Convert.ToBase64String(hash);
    }

}
1
  • Thank you, this is right! I was getting the wrong HMAC because there's a white space on the message i was trying to encrypt
    – Win
    Commented Aug 13, 2019 at 9:00

Not the answer you're looking for? Browse other questions tagged or ask your own question.