I'm trying to work with azure storage in winrt. Since the azure storage client is not compatible with winrt I am trying to use azure's rest API. I am having a heck of a time getting the signature right and I could use another set of eyes to help me see where I'm going wrong.
Azure Account provides a name and key property, this method builds up the request right now simply listing all blobs.
'private async void BuildHTTPRequest(AzureAccount account) { System.Net.Http.HttpClient request = new HttpClient();
request.BaseAddress = new Uri(string.Format("http://{0}.blob.core.windows.net/", account.Name));
// Always have to use UTC date/time
request.DefaultRequestHeaders.Add("x-ms-date", DateTime.UtcNow.ToString("R", CultureInfo.InvariantCulture));
string fmtStringToSign = "{0}\n{1}\n{2}\n{3:R}\n{4}{5}";
request.DefaultRequestHeaders.Add("x-ms-version", "2011-08-18");
string hdr = CanonicalizeHeaders(request.DefaultRequestHeaders);
string authValue = string.Format(fmtStringToSign, "GET", "", "", "", hdr, "");
byte[] signatureByteForm = System.Text.Encoding.UTF8.GetBytes(authValue);
string hashKey = account.Key;
MacAlgorithmProvider macAlgorithmProvider = MacAlgorithmProvider.OpenAlgorithm("HMAC_SHA256");
BinaryStringEncoding encoding = BinaryStringEncoding.Utf8;
var messageBuffer = CryptographicBuffer.ConvertStringToBinary(authValue, encoding);
IBuffer keyBuffer = CryptographicBuffer.ConvertStringToBinary(hashKey, encoding);
CryptographicKey hmacKey = macAlgorithmProvider.CreateKey(keyBuffer);
IBuffer signedMessage = CryptographicEngine.Sign(hmacKey, messageBuffer);
string hashedString = CryptographicBuffer.EncodeToBase64String(signedMessage);
String authHeader = String.Format(CultureInfo.InvariantCulture, "{0} {1}:{2}", "SharedKey",
account.Name, hashedString);
request.DefaultRequestHeaders.Add("Authorization", authHeader);
// Send the request to the queue
try
{
var test1 = request.GetAsync("?comp=list").Result;
if (test1.IsSuccessStatusCode)
{
}
}
catch (WebException ex) { }
}
This should set the headers up for signing...
public string CanonicalizeHeaders(System.Net.Http.Headers.HttpRequestHeaders hdrCollection)
{
StringBuilder retVal = new StringBuilder();// Look for header names that start with "x-ms-" // Then sort them in case-insensitive manner.
List<string> httpStorageHeaderNameArray = new List<string>();
Dictionary<string, string> ht = new Dictionary<string, string>();
foreach (var key in hdrCollection)
{
if (key.Key.ToLowerInvariant().StartsWith("x-ms-", StringComparison.Ordinal))
{
if (ht.ContainsKey(key.Key.ToLowerInvariant()))
{
ht[key.Key.ToLowerInvariant()] = string.Format("{0},{1}", ht[key.Key.ToLowerInvariant()],
hdrCollection.FirstOrDefault(m => m.Key == key.Key).ToString().Replace("\n", string.Empty).Replace("\r", string.Empty).Trim());
}
else
{
httpStorageHeaderNameArray.Add(key.Key.ToLowerInvariant());
ht.Add(key.Key.ToLowerInvariant(),
hdrCollection.FirstOrDefault(m => m.Key == key.Key).Value.FirstOrDefault().ToString().Replace("\n", string.Empty).Replace("\r", string.Empty).Trim());
}
}
}
httpStorageHeaderNameArray.Sort();// Now go through each header's values in the sorted order and append them to the canonicalized string.
foreach (string key in httpStorageHeaderNameArray)
{
retVal.AppendFormat("{0}:{1}\n", key.Trim(), ht[key]);
}
return retVal.ToString();
}
'