2017-04-18 50 views
0

我想用這個例子來計算的S3上傳的AWS4簽名 - http://docs.aws.amazon.com/AmazonS3/latest/API/sigv4-post-example.html的AWS S3如何計算簽名上傳

var exampleSecretKey = "wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY"; 
var exampleBase64EncodedPolicy = "eyAiZXhwaXJhdGlvbiI6ICIyMDE1LTEyLTMwVDEyOjAwOjAwLjAwMFoiLA0KICAiY29uZGl0aW9ucyI6IFsNCiAgICB7ImJ1Y2tldCI6ICJzaWd2NGV4YW1wbGVidWNrZXQifSwNCiAgICBbInN0YXJ0cy13aXRoIiwgIiRrZXkiLCAidXNlci91c2VyMS8iXSwNCiAgICB7ImFjbCI6ICJwdWJsaWMtcmVhZCJ9LA0KICAgIHsic3VjY2Vzc19hY3Rpb25fcmVkaXJlY3QiOiAiaHR0cDovL3NpZ3Y0ZXhhbXBsZWJ1Y2tldC5zMy5hbWF6b25hd3MuY29tL3N1Y2Nlc3NmdWxfdXBsb2FkLmh0bWwifSwNCiAgICBbInN0YXJ0cy13aXRoIiwgIiRDb250ZW50LVR5cGUiLCAiaW1hZ2UvIl0sDQogICAgeyJ4LWFtei1tZXRhLXV1aWQiOiAiMTQzNjUxMjM2NTEyNzQifSwNCiAgICB7IngtYW16LXNlcnZlci1zaWRlLWVuY3J5cHRpb24iOiAiQUVTMjU2In0sDQogICAgWyJzdGFydHMtd2l0aCIsICIkeC1hbXotbWV0YS10YWciLCAiIl0sDQoNCiAgICB7IngtYW16LWNyZWRlbnRpYWwiOiAiQUtJQUlPU0ZPRE5ON0VYQU1QTEUvMjAxNTEyMjkvdXMtZWFzdC0xL3MzL2F3czRfcmVxdWVzdCJ9LA0KICAgIHsieC1hbXotYWxnb3JpdGhtIjogIkFXUzQtSE1BQy1TSEEyNTYifSwNCiAgICB7IngtYW16LWRhdGUiOiAiMjAxNTEyMjlUMDAwMDAwWiIgfQ0KICBdDQp9"; 

var expectedValue = "8afdbf4008c03f22c2cd3cdb72e4afbb1f6a588f3255ac628749a66d7f09699e"; 

var awsSignature = AWS4Signer.ComputeSignature("AKIAIOSFODNN7EXAMPLE", exampleSecretKey, "us-east-1", new DateTime(2015, 12, 29, 0, 0, 0, DateTimeKind.Utc), "s3", "", exampleBase64EncodedPolicy); 

我使用的示例中提供的值但沒有從ComputeSignature方法中獲得預期值。我懷疑這是因爲我爲「signedheaders」參數傳遞了一個空字符串(如果是的話,那麼這是什麼?)。有人可以解釋我做錯了嗎?

+0

您使用哪種庫和語言?你能提供一個你用來啓動上傳的代碼片段嗎? –

+0

這是使用AWS S3 nuget包的c#。我只是試圖使用這些示例在教程中生成相同的簽名 - 我現在已經制定了如何執行。 – Barker1889

回答

0

從來沒有設法讓它與AWS4Signer一起工作,但我設法手動完成它。

using System.Security.Cryptography; 
using System.Text; 

public static class S3UploadSignature 
{ 
    /// <summary> 
    /// Generates the X-Amz-Signature parameter for an S3 upload via the browser 
    /// </summary> 
    /// <param name="base64EncodedPolicy">The upload policy JSON string encoded as base 64</param> 
    /// <param name="awsSecretKey">The AWS secret identity key</param> 
    /// <param name="date">The date the request was signed (yyyyMMdd)</param> 
    /// <param name="regionName">The AWS region the bucket sits in e.g. us-east-1</param> 
    /// <param name="serviceName">The AWS service name e.g. s3</param> 
    public static string Create(string base64EncodedPolicy, string awsSecretKey, string date, string regionName, string serviceName) 
    { 
     var signatureKey = CalculteSignatureKey(awsSecretKey, date, regionName, serviceName); 
     return ToBase16String(HmacSha256(base64EncodedPolicy, signatureKey)); 
    } 

    private static string ToBase16String(byte[] bytes) 
    { 
     var result = new StringBuilder(bytes.Length * 2); 

     foreach (var b in bytes) 
      result.AppendFormat("{0:x2}", b); 

     return result.ToString(); 
    } 

    private static byte[] HmacSha256(string data, byte[] key) 
    { 
     return new HMACSHA256(key).ComputeHash(Encoding.UTF8.GetBytes(data)); 
    } 

    private static byte[] CalculteSignatureKey(string key, string dateStamp, string regionName, string serviceName) 
    { 
     var secret = Encoding.UTF8.GetBytes(("AWS4" + key).ToCharArray()); 
     var date = HmacSha256(dateStamp, secret); 
     var region = HmacSha256(regionName, date); 
     var service = HmacSha256(serviceName, region); 
     var signing = HmacSha256("aws4_request", service); 

     return signing; 
    } 
} 
+0

我沒有使用AWS4Signer,但是閱讀文檔(或者試圖......他們似乎完全符合需要庫文檔包含很少幫助內容的Java標準),這看起來像是用來簽署HTTP請求,不是'POST'政策文件。例如,您提到的「簽名頭文件」與基於表單的上傳文件不是相關的概念,因爲只有策略文件本身實際上是簽名的,而不是頭文件。它與本質上任何其他請求對S3或任何其他AWS服務都是不同的。 –

0

請試試這個。

import com.amazonaws.util.BinaryUtils; 
import org.junit.Assert; 
import org.junit.Test; 

import javax.crypto.Mac; 
import javax.crypto.spec.SecretKeySpec; 
import java.io.UnsupportedEncodingException; 
import java.util.Base64; 

public class AwsTest { 

    @Test 
    public void test() throws Exception { 
     String stringToSign = getStringToSign("<policy_json>"); 
     Assert.assertEquals("eyAiZXhwaXJhdGlvbiI6ICIyMDE1LTEyLTMwVDEyOjAwOjAwLjAwMFoiLA0KICAiY29uZGl0aW9ucyI6IFsNCiAgICB7ImJ1Y2tldCI6ICJzaWd2NGV4YW1wbGVidWNrZXQifSwNCiAgICBbInN0YXJ0cy13aXRoIiwgIiRrZXkiLCAidXNlci91c2VyMS8iXSwNCiAgICB7ImFjbCI6ICJwdWJsaWMtcmVhZCJ9LA0KICAgIHsic3VjY2Vzc19hY3Rpb25fcmVkaXJlY3QiOiAiaHR0cDovL3NpZ3Y0ZXhhbXBsZWJ1Y2tldC5zMy5hbWF6b25hd3MuY29tL3N1Y2Nlc3NmdWxfdXBsb2FkLmh0bWwifSwNCiAgICBbInN0YXJ0cy13aXRoIiwgIiRDb250ZW50LVR5cGUiLCAiaW1hZ2UvIl0sDQogICAgeyJ4LWFtei1tZXRhLXV1aWQiOiAiMTQzNjUxMjM2NTEyNzQifSwNCiAgICB7IngtYW16LXNlcnZlci1zaWRlLWVuY3J5cHRpb24iOiAiQUVTMjU2In0sDQogICAgWyJzdGFydHMtd2l0aCIsICIkeC1hbXotbWV0YS10YWciLCAiIl0sDQoNCiAgICB7IngtYW16LWNyZWRlbnRpYWwiOiAiQUtJQUlPU0ZPRE5ON0VYQU1QTEUvMjAxNTEyMjkvdXMtZWFzdC0xL3MzL2F3czRfcmVxdWVzdCJ9LA0KICAgIHsieC1hbXotYWxnb3JpdGhtIjogIkFXUzQtSE1BQy1TSEEyNTYifSwNCiAgICB7IngtYW16LWRhdGUiOiAiMjAxNTEyMjlUMDAwMDAwWiIgfQ0KICBdDQp9", stringToSign); 

     String signature = getSignature(stringToSign, "wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY", "20151229", "us-east-1", "s3"); 
     Assert.assertEquals("8afdbf4008c03f22c2cd3cdb72e4afbb1f6a588f3255ac628749a66d7f09699e", signature); 
    } 

    private static String getStringToSign(String policy) throws Exception { 
     return Base64.getEncoder().encodeToString(policy.replaceAll("\n", "\r\n").getBytes("UTF-8")); 
    } 

    private static String getSignature(String stringToSign, String secretAccessKey, String dateStamp, String regionName, String serviceName) throws Exception { 
     byte[] signingKey = getSignatureKey(secretAccessKey, dateStamp, regionName, serviceName); 
     return BinaryUtils.toHex(HmacSHA256(stringToSign, signingKey)); 
    } 


    private static byte[] HmacSHA256(String data, byte[] key) throws Exception { 
     String algorithm="HmacSHA256"; 
     Mac mac = Mac.getInstance(algorithm); 
     mac.init(new SecretKeySpec(key, algorithm)); 
     return mac.doFinal(data.getBytes("UTF8")); 
    } 

    private static byte[] getSignatureKey(String key, String dateStamp, String regionName, String serviceName) throws Exception { 
     byte[] kSecret = ("AWS4" + key).getBytes("UTF8"); 
     byte[] kDate = HmacSHA256(dateStamp, kSecret); 
     byte[] kRegion = HmacSHA256(regionName, kDate); 
     byte[] kService = HmacSHA256(serviceName, kRegion); 
     byte[] kSigning = HmacSHA256("aws4_request", kService); 
     return kSigning; 
    } 
}