I found several problems with my code, the biggest was to that i used 2 different timestamps.
AWS SimpleDB - SignatureDoesNotMatch - PCL for Xamarin application
-
06-07-2023 - |
Вопрос
I'm trying to create a SimpleDB persistence framework for a Xamarin component. I can't use the .NET SDK since not all the required assemblies are present in a PCL project. For that reason I'm trying create REST request myself but i keep getting SignatureDoesNotMatch when trying to POST my request.
Can someone help and see if there is something wrong with my signature generation.
Here is the request to be signed
Here is the string being signed
POST\n sdb.amazonaws.com\n /\n &AWSAccessKeyId=AAAAAAAAAAAAAAAAAAAA&Action=PutAttributes&Attribute.1.Name=test&Attribute.1.Value=test&DomainName=test&ItemName=0&SignatureMethod=HmacSHA256&SignatureVersion=2&Timestamp=2014-04-20T11%3A03%3A12%2B02%3A00&Version=2009-04-15
Here is the signed request.
Test AWSAccessKeyId = AAAAAAAAAAAAAAAAAAAA Test AWSSecretKey = BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB
I have included C# files of my hashing and the request builder
public class PutAttributesRequestMarshaller
{
private const string ACTION = "PutAttributes";
private const string METHOD = "POST";
private const string SIGNATURE_METHOD = "HmacSHA256";
private const string SIGNATURE_VERSION = "2";
private const string VERSION = "2009-04-15";
private SortedDictionary<string, string> AttributesDic = new SortedDictionary<string, string> ();
private PutAttributesRequest request;
public PutAttributesRequestMarshaller (PutAttributesRequest request)
{
this.request = request;
for (int i = 0; i < request.Attributes.Count; i++) {
ReplaceableAttribute Attribute = request.Attributes [i];
AttributesDic.Add ("Attribute." + (i + 1) + ".Name", Attribute.Name);
AttributesDic.Add ("Attribute." + (i + 1) + ".Value", Attribute.Value);
if (Attribute.Replace.Value) {
AttributesDic.Add ("Attribute." + (i + 1) + ".Replace", Attribute.Replace.ToString ().ToLower ());
}
}
}
public String Marshal ()
{
StringBuilder sb = new StringBuilder ();
sb.Append ("https://" + Region + "/");
sb.Append ("?Action=" + ACTION);
sb.Append ("&DomainName=" + request.DomainName);
sb.Append ("&ItemName=" + request.ItemName);
sb.Append (Attributes);
sb.Append ("&Version=" + VERSION);
sb.Append ("&Timestamp=" + Timestamp);
string signature = GenerateSignature ();
string encoded = System.Net.WebUtility.UrlEncode (signature);
sb.Append ("&Signature=" + encoded);
sb.Append ("&SignatureVersion=" + SIGNATURE_VERSION);
sb.Append ("&SignatureMethod=" + SIGNATURE_METHOD);
sb.Append ("&AWSAccessKeyId=" + AWSAccessKeyId);
return sb.ToString ();
}
private string Attributes {
get {
StringBuilder sb = new StringBuilder ();
var enumerator = AttributesDic.GetEnumerator ();
while (enumerator.MoveNext ()) {
var entry = enumerator.Current;
sb.Append ("&");
sb.Append (System.Net.WebUtility.UrlEncode (entry.Key));
sb.Append ("=");
sb.Append (System.Net.WebUtility.UrlEncode (entry.Value));
}
return sb.ToString ();
}
}
private string AWSAccessKeyId {
get {
return ServiceContainer.Resolve<SimpleDBClient> ().AWSAccessKeyId;
}
}
private string AWSSecretKey {
get {
return ServiceContainer.Resolve<SimpleDBClient> ().AWSSecretKey;
}
}
private string Timestamp {
get {
DateTime withOutMili = DateTime.Now;
string formatted = withOutMili.ToString ("yyyy-MM-ddTHH:mm:sszzzzz");
string encoded = System.Net.WebUtility.UrlEncode (formatted);
return encoded;
}
}
public string Region {
get {
return ServiceContainer.Resolve<SimpleDBClient> ().Region;
}
}
private string GenerateSignature ()
{
StringBuilder sb = new StringBuilder ();
sb.Append (METHOD + "\n");
sb.Append (Region + "\n");
sb.Append ("/\n");
sb.Append ("&AWSAccessKeyId=" + AWSAccessKeyId);
sb.Append ("&Action=" + ACTION);
sb.Append (Attributes);
sb.Append ("&DomainName=" + request.DomainName);
sb.Append ("&ItemName=" + request.ItemName);
sb.Append ("&SignatureMethod=" + SIGNATURE_METHOD);
sb.Append ("&SignatureVersion=" + SIGNATURE_VERSION);
sb.Append ("&Timestamp=" + Timestamp);
sb.Append ("&Version=" + VERSION);
string signature = sb.ToString ();
ISHA256Service service = ServiceContainer.Resolve<ISHA256Service> ();
string hashed = service.CreateHash (signature, AWSSecretKey);
return hashed;
}
private SimpleDBClient Client {
get {
return ServiceContainer.Resolve<SimpleDBClient> ();
}
}
public string CreateHash (string message, string secret)
{
var encoding = new System.Text.ASCIIEncoding ();
byte[] keyByte = encoding.GetBytes (secret);
byte[] messageBytes = encoding.GetBytes (message);
using (var hmacsha256 = new HMACSHA256 (keyByte)) {
byte[] hashmessage = hmacsha256.ComputeHash (messageBytes);
return Convert.ToBase64String (hashmessage);
}
}
Thank you in advance.
Решение