AWS SimpleDB - SignatureDoesNotMatch - PCL для приложения Xamarin

Я пытаюсь создать постоянную среду SimpleDB для компонента Xamarin. Я не могу использовать.NET SDK, так как не все необходимые сборки присутствуют в проекте PCL. По этой причине я пытаюсь создать запрос REST самостоятельно, но я продолжаю получать SignatureDoesNotMatch при попытке отправить мой запрос.

Может кто-нибудь помочь и посмотреть, если что-то не так с моим поколением подписей.

Вот просьба подписаться

https://sdb.amazonaws.com/?Action=PutAttributes&DomainName=test&ItemName=0&Attribute.1.Name=test&Attribute.1.Value=test&AWSAccessKeyId=AAAAAAAAAAAAAAAAAAAA&Version=2009-04-15&SignatureVersion=2&SignatureMethod=HmacSHA256&Timestamp=2014-04-20T11%3A04%3A10%2B02%3A00

Вот строка подписывается

POST\n sdb.amazonaws.com\n /\n &AWSAccessKeyId=AAAAAAAAAAAAAAAAAAAA&Action=PutAttributes&Attribute.1. % 3A00&Version=2009-04-15

Вот подписанный запрос.

https://sdb.amazonaws.com/?Action=PutAttributes&DomainName=test&ItemName=0&Attribute.1.Name=test&Attribute.1.Value=test&AWSAccessKeyId=AAAAAAAAAAAAAAAAAAAA&Version=2009-04-15&Signature=h0lNLh%2BfpDLzM2ipBozPnH6dDKFU%2BFTDwH82H42ptI8%3D&SignatureVersion=2&SignatureMethod=HmacSHA256&Timestamp=2014-04-20T11%3A05%3A05%2B02%3A00

Тест AWSAccessKeyId = AAAAAAAAAAAAAAAAAAAA Тест AWSSecretKey = BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB

Я включил C# файлы моего хеширования и построителя запросов

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);
        }
    }

Заранее спасибо.

1 ответ

Решение

Я обнаружил несколько проблем с моим кодом, самая большая из которых заключалась в том, что я использовал 2 разные метки времени.

Другие вопросы по тегам