2
votes

We are trying to access the blobs from azure blob storage without using the Azure SDK,

we are trying to access through the shared key by Azure REST API, for that we need to generate the Authorization header, but when I try to create a signature from the Access key I am getting the following error

"Server failed to authenticate the request. Make sure the value of Authorization header is formed correctly including the signature."

"The MAC signature found in the HTTP request 'key hash' is not the same as any computed signature"

Need help to generate proper authorization header, we have followed the documentation

https://docs.microsoft.com/en-us/rest/api/storageservices/authorize-with-shared-key

https://docs.microsoft.com/en-gb/rest/api/storageservices/authorization-for-the-azure-storage-services?redirectedfrom=MSDN

We have tried in postman as well, and we are getting the same error.

     string signWithAccountKey(string stringToSign, string accountKey)
     {
            var hmacsha = new System.Security.Cryptography.HMACSHA256();
            hmacsha.Key = Convert.FromBase64String(accountKey);
            var signature = hmacsha.ComputeHash(Encoding.UTF8.GetBytes(stringToSign));
            return Convert.ToBase64String(signature);
     }

The MAC signature found in the HTTP request 'key hash' is not the same as any computed signature

1
Please edit your question share the complete code. Also tell us what REST API operation you're trying to perform. More than likely you're doing something incorrectly while computing stringToSign.Gaurav Mantri
Hello Naik, can you resolve your issue as per the answer blow? if it's resolved, please help mark it as an answer? Thanks. Follow this guide on how to mark.Ivan Yang

1 Answers

1
votes

I write the code below for List Blobs api. You can follow/modify my code and try to use other blobs api.

class Program
{

  static void Main(string[] args)
   {
     ListBlobs();

      Console.WriteLine("done");
      Console.ReadLine();    
   }  


static void ListBlobs()
{
    string Account = "xxxx";
    string Key = "xxxx";
    string Container = "aa1";
    string apiversion = "2018-03-28";

    DateTime dt = DateTime.UtcNow;
    string StringToSign = String.Format("GET\n"
        + "\n" // content encoding
        + "\n" // content language
        + "\n" // content length
        + "\n" // content md5
        + "\n" // content type
        + "\n" // date
        + "\n" // if modified since
        + "\n" // if match
        + "\n" // if none match
        + "\n" // if unmodified since
        + "\n" // range
        + "x-ms-date:" + dt.ToString("R") + "\nx-ms-version:"+apiversion+"\n" // headers
        + "/{0}/{1}\ncomp:list\nrestype:container", Account, Container);

    string auth = SignThis(StringToSign, Key, Account);

    Console.WriteLine($"the date is: {dt.ToString("R")}");
    Console.WriteLine($"the auth token is: {auth}");
    Console.WriteLine("*********");
    string method = "GET";
    string urlPath = string.Format("https://{0}.blob.core.windows.net/{1}?restype=container&comp=list", Account, Container);
    Uri uri = new Uri(urlPath);
    HttpWebRequest request = (HttpWebRequest)WebRequest.Create(uri);
    request.Method = method;
    request.Headers.Add("x-ms-date", dt.ToString("R"));
    request.Headers.Add("x-ms-version", apiversion);
    request.Headers.Add("Authorization", auth);

    Console.WriteLine("***list all the blobs in the specified container, in xml format***");
    using (HttpWebResponse response = (HttpWebResponse)request.GetResponse())
    {

        using (StreamReader reader = new StreamReader(response.GetResponseStream()))
        {
            Console.WriteLine(reader.ReadToEnd());
        }
    }
}


private static String SignThis(String StringToSign, string Key, string Account)
        {
            String signature = string.Empty;
            byte[] unicodeKey = Convert.FromBase64String(Key);
            using (HMACSHA256 hmacSha256 = new HMACSHA256(unicodeKey))
            {
                Byte[] dataToHmac = System.Text.Encoding.UTF8.GetBytes(StringToSign);
                signature = Convert.ToBase64String(hmacSha256.ComputeHash(dataToHmac));
            }

            String authorizationHeader = String.Format(
                  CultureInfo.InvariantCulture,
                  "{0} {1}:{2}",
                  "SharedKey",
                  Account,
                  signature);

            return authorizationHeader;
        }


   }

Test result in visual studio, and in postman:

enter image description here