如何计算AWS S3上载的签名

时间:2017-04-18 16:00:16

标签: amazon-web-services amazon-s3

我正在尝试使用此示例来计算s3上传的AWS4签名 -  http://docs.aws.amazon.com/AmazonS3/latest/API/sigv4-post-example.html

cols <- c("x","y")

availabilityfunction <- function(i){
  DT[,paste0("avail_",i):=paste0(
       as.character(min(ifelse(!is.na(i),time,NA),na.rm=T)),
       "-",
       as.character(max(ifelse(!is.na(i),time,NA),na.rm=T))),
    by=id]}
lapply(cols,availabilityfunction)

我正在使用示例中提供的值,但未从ComputeSignature方法获取预期值。我怀疑是因为我传入一个空字符串来表示“签名者”的论点(如果是的话那么这应该是什么?)。有人可以解释一下我做错了吗?

2 个答案:

答案 0 :(得分: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;
    }
}

答案 1 :(得分: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;
    }
}