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#?
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#?
Share Improve this question asked Aug 9, 2019 at 3:21 WinWin 991 gold badge1 silver badge10 bronze badges 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? – ProgrammingLlama Commented Aug 9, 2019 at 4:37
1 Answer
Reset to default 15for 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);
}
}