using System.Text;
using System.Net;
using System.IO;
using System.Xml;
using System.Xml.XPath;
using System.Collections.Generic;
using System.Web;
using System.Security.Cryptography;
public partial class _Default : System.Web.UI.Page
{
private const string MY_AWS_ACCESS_KEY_ID = "xxxxxxxxxxx";
private const string MY_AWS_SECRET_KEY = "asasasasasasasasasasasasasasasasas";
private const string DESTINATION = "ecs.amazonaws.com";
private const string NAMESPACE = "http://webservices.amazon.com/AWSECommerceService/2009-03-31";
private const string ITEM_ID = "B000ERVMI8";
private string endPoint;
private string akid;
private byte[] secret;
private HMAC signer;
private const string REQUEST_URI = "/onca/xml";
private const string REQUEST_METHOD = "GET";
protected void Page_Load(object sender, EventArgs e)
{
// SignedRequestHelper helper = new SignedRequestHelper(MY_AWS_ACCESS_KEY_ID, MY_AWS_SECRET_KEY, DESTINATION);
SignedRequestHelper(MY_AWS_ACCESS_KEY_ID, MY_AWS_SECRET_KEY, DESTINATION);
string requestString = "Service=AWSECommerceService&Version=2009-03-31&Operation=ItemLookup&ResponseGroup=Small&ItemId=" + ITEM_ID;
string requestUrl = Sign(requestString);
string title = FetchTitle(requestUrl);
Response.Write("Method 2: Query String form.");
Response.Write("Title is \"" + title + "\"");
//System.Console.WriteLine();
//System.Console.WriteLine("Hit Enter to end");
//System.Console.ReadLine();
}
private static string FetchTitle(string url)
{
try
{
WebRequest request = HttpWebRequest.Create(url);
WebResponse response = request.GetResponse();
XmlDocument doc = new XmlDocument();
doc.Load(response.GetResponseStream());
XmlNode titleNode = doc.GetElementsByTagName("Title", NAMESPACE).Item(0);
string title = titleNode.InnerText;
return title;
}
catch (Exception e)
{
System.Console.WriteLine("Caught Exception: " + e.Message);
System.Console.WriteLine("Stack Trace: " + e.StackTrace);
}
return null;
}
public void SignedRequestHelper(string awsAccessKeyId, string awsSecretKey, string destination)
{
this.endPoint = destination.ToLower();
this.akid = awsAccessKeyId;
this.secret = Encoding.UTF8.GetBytes(awsSecretKey);
this.signer = new HMACSHA256(this.secret);
}
public string Sign(IDictionary<string, string> request)
{
ParamComparer pc = new ParamComparer();
SortedDictionary<string, string> sortedMap = new SortedDictionary<string, string>(request, pc);
sortedMap["AWSAccessKeyId"] = this.akid;
sortedMap["Timestamp"] = this.GetTimestamp();
// Get the canonical query string
string canonicalQS = this.ConstructCanonicalQueryString(sortedMap);
// Derive the bytes needs to be signed.
StringBuilder builder = new StringBuilder();
builder.Append(REQUEST_METHOD)
.Append("\n")
.Append(this.endPoint)
.Append("\n")
.Append(REQUEST_URI)
.Append("\n")
.Append(canonicalQS);
string stringToSign = builder.ToString();
byte[] toSign = Encoding.UTF8.GetBytes(stringToSign);
// Compute the signature and convert to Base64.
byte[] sigBytes = signer.ComputeHash(toSign);
string signature = Convert.ToBase64String(sigBytes);
// now construct the complete URL and return to caller.
StringBuilder qsBuilder = new StringBuilder();
qsBuilder.Append("http://")
.Append(this.endPoint)
.Append(REQUEST_URI)
.Append("?")
.Append(canonicalQS)
.Append("&Signature=")
.Append(this.PercentEncodeRfc3986(signature));
return qsBuilder.ToString();
}
public string Sign(string queryString)
{
IDictionary<string, string> request = this.CreateDictionary(queryString);
return this.Sign(request);
}
private string GetTimestamp()
{
DateTime currentTime = DateTime.UtcNow;
string timestamp = currentTime.ToString("yyyy-MM-ddTHH:mm:ssZ");
return timestamp;
}
private string PercentEncodeRfc3986(string str)
{
str = HttpUtility.UrlEncode(str, System.Text.Encoding.UTF8);
str.Replace("'", "%27").Replace("(", "%28").Replace(")", "%29").Replace("*", "%2A").Replace("!", "%21").Replace("%7e", "~");
StringBuilder sbuilder = new StringBuilder(str);
for (int i = 0; i < sbuilder.Length; i++)
{
if (sbuilder[i] == '%')
{
if (Char.IsDigit(sbuilder[i + 1]) && Char.IsLetter(sbuilder[i + 2]))
{
sbuilder[i + 2] = Char.ToUpper(sbuilder[i + 2]);
}
}
}
return sbuilder.ToString();
}
private IDictionary<string, string> CreateDictionary(string queryString)
{
Dictionary<string, string> map = new Dictionary<string, string>();
string[] requestParams = queryString.Split('&');
for (int i = 0; i < requestParams.Length; i++)
{
if (requestParams[i].Length < 1)
{
continue;
}
char[] sep = { '=' };
string[] param = requestParams[i].Split(sep, 2);
for (int j = 0; j < param.Length; j++)
{
param[j] = HttpUtility.UrlDecode(param[j], System.Text.Encoding.UTF8);
}
switch (param.Length)
{
case 1:
{
if (requestParams[i].Length >= 1)
{
if (requestParams[i].ToCharArray()[0] == '=')
{
map[""] = param[0];
}
else
{
map[param[0]] = "";
}
}
break;
}
case 2:
{
if (!string.IsNullOrEmpty(param[0]))
{
map[param[0]] = param[1];
}
}
break;
}
}
return map;
}
private string ConstructCanonicalQueryString(SortedDictionary<string, string> sortedParamMap)
{
StringBuilder builder = new StringBuilder();
if (sortedParamMap.Count == 0)
{
builder.Append("");
return builder.ToString();
}
foreach (KeyValuePair<string, string> kvp in sortedParamMap)
{
builder.Append(this.PercentEncodeRfc3986(kvp.Key));
builder.Append("=");
builder.Append(this.PercentEncodeRfc3986(kvp.Value));
builder.Append("&");
}
string canonicalString = builder.ToString();
canonicalString = canonicalString.Substring(0, canonicalString.Length - 1);
return canonicalString;
}
}
class ParamComparer : IComparer<string>
{
public int Compare(string p1, string p2)
{
return string.CompareOrdinal(p1, p2);
}
}
8 comments:
Superb, thanks a lot!! You saved me lot of time.
I use the same algorithm for signing the request, but I can't seem to generate the same signature as Amazon does.
I even tried out their Signed Requests Helper and still kept on getting a different signature.
Help will be appreciated.
thanks
Where can I get the library that has the SignedRequestHelper class?
Really you are big madarchod. The code you written saves a lot of time and away my frustration from Signature. Really awesome....
thank you bro it helped me god bless you
Post a Comment