AWS SimpleDB - SignatureDoesNotMatch - 用于Xamarin应用程序的PCL

时间:2014-04-20 10:54:28

标签: rest post hmac sha256 amazon-simpledb

我正在尝试为Xamarin组件创建SimpleDB持久性框架。我不能使用.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&安培;动作= PutAttributes&安培; Attribute.1.Name =试验&安培; Attribute.1.Value =试验&安培;域名=试验&安培; ITEMNAME = 0&安培;是SignatureMethod = HmacSHA256&安培; SignatureVersion = 2及时间戳= 2014-04-20T11% 3A03 3A12%2B02%%3A00&安培;版本= 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 = BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB

我已经包含了我的哈希的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 个答案:

答案 0 :(得分:0)

我发现我的代码存在一些问题,最大的问题是我使用了2个不同的时间戳。