2017-02-14 92 views
2

我生病看到這樣的反應:AWS S3直接上傳回報無效的簽名(第4版簽名)

我們計算出你所提供的簽名不匹配的請求籤名。檢查你的密鑰和簽名方法。

我知道的版本這個問題已經在這裏找到答案:

SO - AWS S3 browser upload using HTTP POST gives invalid signature

而且我跟了,沒有運氣它的每一個細節,我可能失去了一些東西簡單。我使用C#來生成策略和v4 Aws簽名。下面是政策代碼:

var policyBuilder = new StringBuilder(); 

policyBuilder.AppendFormat("{{ \"expiration\": \"{0}\",\r\n", "2017-12-30T12:00:00.000Z"); 
policyBuilder.Append(" \"conditions\": [\r\n"); 
policyBuilder.Append(" [\"starts-with\", \"$key\", \"\"],\r\n"); 
policyBuilder.AppendFormat(" {{\"x-amz-credential\": \"{1}\"}},\r\n", <MyAccessKey>/20170214/us-east-2/s3/aws4_request)); 
policyBuilder.Append(" {\"x-amz-algorithm\": \"AWS4-HMAC-SHA256\"},\r\n"); 
policyBuilder.Append(" {\"x-amz-date\": \"20170214T000000Z\" }\r\n"); 
policyBuilder.Append(" ]\r\n}"); 

var policyString = policyBuilder.ToString(); 
var policyStringBytes = Encoding.UTF8.GetBytes(policyString); 
return Convert.ToBase64String(policyStringBytes); 

這是用來生成簽名的代碼:

static byte[] HmacSHA256(String data, byte[] key) 
{ 
    String algorithm = "HmacSHA256"; 
    KeyedHashAlgorithm kha = KeyedHashAlgorithm.Create(algorithm); 
    kha.Key = key; 

    return kha.ComputeHash(Encoding.UTF8.GetBytes(data)); 
} 

static byte[] GetSignatureKey(String key, String dateStamp, String regionName, String serviceName) 
{ 
    byte[] kSecret = Encoding.UTF8.GetBytes(("AWS4" + key).ToCharArray()); 
    byte[] kDate = HmacSHA256(dateStamp, kSecret); 
    byte[] kRegion = HmacSHA256(regionName, kDate); 
    byte[] kService = HmacSHA256(serviceName, kRegion); 
    byte[] kSigning = HmacSHA256("aws4_request", kService); 

    return kSigning; 
} 

public static string ToHexString(byte[] data, bool lowercase) 
{ 
    var sb = new StringBuilder(); 
    for (var i = 0; i < data.Length; i++) 
    { 
     sb.Append(data[i].ToString(lowercase ? "x2" : "X2")); 
    } 
    return sb.ToString(); 
} 

帶來其結合在一起的方法:

public string GetS3PolicySignatureV4(string policy) 
{ 
    byte[] signingKey = GetSignatureKey(<MySecretKey>, "20170214T000000Z", "us-east-2", "s3"); 
    byte[] signature = HmacSHA256(policy, signingKey); 
    return AWS4SignerBase.ToHexString(signature, true); 
} 

這裏是HTML表單:

<form action="http://<BucketName>.s3.amazonaws.com/" method="post" enctype="multipart/form-data"> 
    <input type="hidden" name="key" value="<FileKey>" /> 
    <input type="hidden" name="x-amz-credential" value="<MyAccessKey>/20170214/us-east-2/s3/aws4_request"/> 
    <input type="hidden" name="x-amz-algorithm" value="AWS4-HMAC-SHA256" /> 
    <input type="hidden" name="x-amz-date" value="20170214T000000Z" /> 
    <input type="hidden" name="policy" value='<Base64PolicyResult>' /> 
    <input type="hidden" name="x-amz-signature" value="<GenerateSignature>" /> 
    File: 
    <input type="file" name="file" /> <br /> 
    <input type="submit" name="submit" value="Upload to Amazon S3" /> 
</form> 

我有版本指明分數,在該示例的示例策略的結果:

AWS - Examples: Browser-Based Upload using HTTP POST (Using AWS Signature Version 4)

以及所得簽名使用所提供的參數和密鑰相匹配的例子。但是當我嘗試POST到S3時,我總是得到那個可怕的迴應。

+0

我想我找到了沃爾多。從示例中,您的策略文檔中缺少'{「bucket」:「sigv4examplebucket」}。 –

+0

@ Michael-sqlbot我在策略中也嘗試過使用「bucket」,事實上所有的策略選項都包含在該示例中。根據這個http://docs.aws.amazon.com/AmazonS3/latest/API/sigv4-authentication-HTTPPOST.html,策略中唯一需要的元素是:x-amz-algorithm,x-amz-credential和x-amz-date。基於計算簽名的方法(我從這裏獲得:http://docs.aws.amazon.com/general/latest/gr/signature-v4-examples.html#signature-v4-examples-dotnet)政策的內容應該無關緊要地計算簽名。 – gsxrboy73

+0

什麼?! Noooooo。這是創建*簽名密鑰的算法* - 不是簽名。您使用簽名密鑰來創建政策的base64表示形式的簽名*。策略中的單個字節不同會顯着改變簽名。簽名保護策略免受篡改,然後策略確定請求是否有效,因爲表單與策略匹配。 –

回答

2

問題是傳入GetSignatureKey方法的日期格式不正確。應該只是「20170214」,隱藏表單字段x-amz-date是「20170214T000000Z」的ISO8601格式。我將相同的值傳入GetSignatureKey方法。

+0

嗨,我想用你發佈的相同的代碼,我改變了你在答案中提到的日期。我仍然得到同樣的錯誤。 @ gsxrboy73你有什麼想法嗎?我也發佈我的問題在這裏:https://stackoverflow.com/questions/49184746/aws-s3-direct-upload-returns-invalid-signature-version-4-signature-c-sharp – ali