在Elixir中S3签署浏览器POST命令

时间:2016-07-02 19:07:56

标签: amazon-web-services amazon-s3 elixir

我正在努力完成S3 signing example。但我没有在他们的文档中得到临时答案。我从iex开始:

policy = %{"conditions"=> [
        %{"bucket"=> "sigv4examplebucket"},
        ["starts-with", "$key", "user/user1/"],
        %{"acl"=> "public-read"},
        %{"success_action_redirect"=> "http=>//sigv4examplebucket.s3.amazonaws.com/successful_upload.html"},
        ["starts-with", "$Content-Type", "image/"],
        %{"x-amz-meta-uuid"=> "14365123651274"},
        %{"x-amz-server-side-encryption"=> "AES256"},
        ["starts-with", "$x-amz-meta-tag", ""],
        %{"x-amz-credential"=> "AKIAIOSFODNN7EXAMPLE/20151229/us-east-1/s3/aws4_request"},
        %{"x-amz-algorithm"=> "AWS4-HMAC-SHA256"},
        %{"x-amz-date"=> "20151229T000000Z"}
      ]
    }

stringToSign = policy |> Poison.encode! |> Base.encode64

但是stringToSign比亚马逊的例子更短。

签名我有这些助手:

@secret_key "wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY"

def signing_key2(secret, date, region, service) do
    hash_sha256("AWS4" <> secret, date)
    |> hash_sha256(region)
    |> hash_sha256(service)
    |> hash_sha256("aws4_request")
end

def hash_sha256(secret, msg) do
  hash_sha256_bis(secret, msg)
  |> Base.url_encode64
end

def hash_sha256_bis(secret, msg) do
  :crypto.hmac(:sha256, secret, msg)
end

然后跑

signing_key2(@secret_key, "20151229", "us-east-1", "s3")

但这比测试答案短。欢迎一些指点。

2 个答案:

答案 0 :(得分:1)

如果你从亚马逊的例子解码base64字符串,你会注意到他们使用\ r \ n作为换行符:

iex(25)> Base.decode64("eyAiZXhwaXJhdGlvbiI6ICIyMDE1LTEyLTMwVDEyOjAwOjAwLjAwMFoiLA0KICAiY29uZGl0aW9ucyI6IFsNCiAgICB7ImJ1Y2tldCI6ICJzaWd2NGV4YW1wbGVidWNrZXQifSwNCiAgICBbInN0YXJ0cy13aXRoIiwgIiRrZXkiLCAidXNlci91c2VyMS8iXSwNCiAgICB7ImFjbCI6ICJwdWJsaWMtcmVhZCJ9LA0KICAgIHsic3VjY2Vzc19hY3Rpb25fcmVkaXJlY3QiOiAiaHR0cDovL3NpZ3Y0ZXhhbXBsZWJ1Y2tldC5zMy5hbWF6b25hd3MuY29tL3N1Y2Nlc3NmdWxfdXBsb2FkLmh0bWwifSwNCiAgICBbInN0YXJ0cy13aXRoIiwgIiRDb250ZW50LVR5cGUiLCAiaW1hZ2UvIl0sDQogICAgeyJ4LWFtei1tZXRhLXV1aWQiOiAiMTQzNjUxMjM2NTEyNzQifSwNCiAgICB7IngtYW16LXNlcnZlci1zaWRlLWVuY3J5cHRpb24iOiAiQUVTMjU2In0sDQogICAgWyJzdGFydHMtd2l0aCIsICIkeC1hbXotbWV0YS10YWciLCAiIl0sDQoNCiAgICB7IngtYW16LWNyZWRlbnRpYWwiOiAiQUtJQUlPU0ZPRE5ON0VYQU1QTEUvMjAxNTEyMjkvdXMtZWFzdC0xL3MzL2F3czRfcmVxdWVzdCJ9LA0KICAgIHsieC1hbXotYWxnb3JpdGhtIjogIkFXUzQtSE1BQy1TSEEyNTYifSwNCiAgICB7IngtYW16LWRhdGUiOiAiMjAxNTEyMjlUMDAwMDAwWiIgfQ0KICBdDQp9")
{:ok,
 "{ \"expiration\": \"2015-12-30T12:00:00.000Z\",\r\n  \"conditions\": [\r\n    {\"bucket\": \"sigv4examplebucket\"},\r\n    [\"starts-with\", \"$key\", \"user/user1/\"],\r\n    {\"acl\": \"public-read\"},\r\n    {\"success_action_redirect\": \"http://sigv4examplebucket.s3.amazonaws.com/successful_upload.html\"},\r\n    [\"starts-with\", \"$Content-Type\", \"image/\"],\r\n    {\"x-amz-meta-uuid\": \"14365123651274\"},\r\n    {\"x-amz-server-side-encryption\": \"AES256\"},\r\n    [\"starts-with\", \"$x-amz-meta-tag\", \"\"],\r\n\r\n    {\"x-amz-credential\": \"AKIAIOSFODNN7EXAMPLE/20151229/us-east-1/s3/aws4_request\"},\r\n    {\"x-amz-algorithm\": \"AWS4-HMAC-SHA256\"},\r\n    {\"x-amz-date\": \"20151229T000000Z\" }\r\n  ]\r\n}"}

还要注意那里的双重换行,你也不会从Poison那里获得。为了得到完全相同的base64结果,你可以这样做:

s = ~s({ "expiration": "2015-12-30T12:00:00.000Z",
  "conditions": [
    {"bucket": "sigv4examplebucket"},
    ["starts-with", "$key", "user/user1/"],
    {"acl": "public-read"},
    {"success_action_redirect": "http://sigv4examplebucket.s3.amazonaws.com/successful_upload.html"},
    ["starts-with", "$Content-Type", "image/"],
    {"x-amz-meta-uuid": "14365123651274"},
    {"x-amz-server-side-encryption": "AES256"},
    ["starts-with", "$x-amz-meta-tag", ""],

    {"x-amz-credential": "AKIAIOSFODNN7EXAMPLE/20151229/us-east-1/s3/aws4_request"},
    {"x-amz-algorithm": "AWS4-HMAC-SHA256"},
    {"x-amz-date": "20151229T000000Z" }
  ]
})
iex(24)> s |> String.replace("\n", "\r\n") |> Base.encode64
"eyAiZXhwaXJhdGlvbiI6ICIyMDE1LTEyLTMwVDEyOjAwOjAwLjAwMFoiLA0KICAiY29uZGl0aW9ucyI6IFsNCiAgICB7ImJ1Y2tldCI6ICJzaWd2NGV4YW1wbGVidWNrZXQifSwNCiAgICBbInN0YXJ0cy13aXRoIiwgIiRrZXkiLCAidXNlci91c2VyMS8iXSwNCiAgICB7ImFjbCI6ICJwdWJsaWMtcmVhZCJ9LA0KICAgIHsic3VjY2Vzc19hY3Rpb25fcmVkaXJlY3QiOiAiaHR0cDovL3NpZ3Y0ZXhhbXBsZWJ1Y2tldC5zMy5hbWF6b25hd3MuY29tL3N1Y2Nlc3NmdWxfdXBsb2FkLmh0bWwifSwNCiAgICBbInN0YXJ0cy13aXRoIiwgIiRDb250ZW50LVR5cGUiLCAiaW1hZ2UvIl0sDQogICAgeyJ4LWFtei1tZXRhLXV1aWQiOiAiMTQzNjUxMjM2NTEyNzQifSwNCiAgICB7IngtYW16LXNlcnZlci1zaWRlLWVuY3J5cHRpb24iOiAiQUVTMjU2In0sDQogICAgWyJzdGFydHMtd2l0aCIsICIkeC1hbXotbWV0YS10YWciLCAiIl0sDQoNCiAgICB7IngtYW16LWNyZWRlbnRpYWwiOiAiQUtJQUlPU0ZPRE5ON0VYQU1QTEUvMjAxNTEyMjkvdXMtZWFzdC0xL3MzL2F3czRfcmVxdWVzdCJ9LA0KICAgIHsieC1hbXotYWxnb3JpdGhtIjogIkFXUzQtSE1BQy1TSEEyNTYifSwNCiAgICB7IngtYW16LWRhdGUiOiAiMjAxNTEyMjlUMDAwMDAwWiIgfQ0KICBdDQp9"

不太确定如何计算最终签名,但这解释了编码的base64字符串的不同值。

答案 1 :(得分:1)

您正在错误地创建派生密钥。你不应该使用base64编码中间的hmac结果。

只有要签名的实际字符串的hmac需要任何编码,只需要在基数16中输出(通过Base.encode16(case: :lower)