C# .NET: Create AWS SDK Calls and Signing Them with .NET

10/5/2014 4:16:35 PM

The following code is using the Amazon Alexa Web Information Service to pull site information. You create the url, with query strings, and sign the request.

string awsAccessId = "MyAccessId";
string awsSecretKey = "MySecretKey";
string alexaUrl = "http://awis.amazonaws.com/?";

Dictionary<string, string> queryStringList = new Dictionary<string, string>();    

string timeStamp = System.DateTime.UtcNow.ToString("yyyy-MM-ddTHH:mm:ss.fffZ", System.Globalization.CultureInfo.InvariantCulture);

queryStringList.Add("Url", "google.com");
queryStringList.Add("Action", "UrlInfo");
queryStringList.Add("Count", "10");
queryStringList.Add("ResponseGroup", "Rank,ContactInfo,Categories,UsageStats,Keywords,SiteData,LinksInCount");
queryStringList.Add("SignatureMethod", "HmacSHA256");
queryStringList.Add("SignatureVersion", "2");
queryStringList.Add("Start", "1");
queryStringList.Add("Timestamp", timeStamp);

//sort
queryStringList = queryStringList.OrderBy(x => x.Key).ToDictionary(x => x.Key, x => x.Value);

//query strings must be urlencode with special characters being in uppercase, .NET does not do this by default
//must use custom method

//access key must be first in the query string
string queryString = "";
queryString = "AWSAccessKeyId=" + UpperCaseUrlEncode(awsAccessId) + "&";

//url encode query string values
foreach (var item in queryStringList)
{
	queryString += item.Key + "=" + UpperCaseUrlEncode(item.Value) + "&";
}

//remove trailing &
queryString = queryString.TrimEnd(new char[] { '&' });

alexaUrl += queryString;

//must create signature
string stringToEncode = "GET\nawis.amazonaws.com\n/\n" + queryString;

System.Security.Cryptography.HMACSHA256 provider = new System.Security.Cryptography.HMACSHA256(System.Text.Encoding.UTF8.GetBytes(awsSecretKey));

byte[] tmpSource;
byte[] tmpHash;

//Create a byte array from source data.
tmpSource = System.Text.Encoding.UTF8.GetBytes(stringToEncode);

//Compute hash based on source data.
tmpHash = provider.ComputeHash(tmpSource);

//Convert hash to string
string endcodeQueryString = Convert.ToBase64String(tmpHash, 0, tmpHash.Length);		

alexaUrl += "&Signature=" + Server.UrlEncode(endcodeQueryString);   

...

//method to url encode a value with uppercase values for special characters
public static string UpperCaseUrlEncode(string value)
{
	char[] temp = HttpUtility.UrlEncode(value).ToCharArray();
	for (int i = 0; i < temp.Length - 2; i++)
	{
		if (temp[i] == '%')
		{
			temp[i + 1] = char.ToUpper(temp[i + 1]);
			temp[i + 2] = char.ToUpper(temp[i + 2]);
		}
	}
	return new string(temp);
}