Python生成的S3 POST签名

6 投票
1 回答
4125 浏览
提问于 2025-04-17 11:08

我觉得我几乎看完了关于在浏览器中使用表单向S3发送的签名的base-64编码的所有资料,包括旧的和新的文档。例如:

http://doc.s3.amazonaws.com/proposals/post.html

我甚至还找到了这个:

http://s3.amazonaws.com/doc/s3-example-code/post/post_sample.html

与其使用上面的链接或亚马逊的新政策生成器,或者去折腾Boto,我想写一个简单的.py脚本,从一个文本文件(policy.txt)中提取政策的JSON,然后生成必要的base-64编码签名,以帮助我编写HTML表单。

但是,签名本身(依赖于编码后的政策)没有正确编码……可能是因为某种utf-8和ascii的区别,或者是\n(换行符)的问题?

我正在使用的脚本如下,政策和AWS的秘密密钥private_key来自我用来测试这个脚本的AWS案例。亚马逊提供的正确编码的签名在下面的脚本中作为参考。

有没有人能告诉我,为什么下面计算出的签名与亚马逊提供的参考签名不匹配?

换句话说:

为什么这个是正确编码的:

policy_encoded = base64.b64encode(policy)

但这个却不是:

signature = base64.b64encode(hmac.new(private_key, policy_encoded, sha).digest())

PYTHON签名计算器……

#!/usr/bin/env python
# -*- coding: utf-8 -*-

import base64, hmac, sha
from sys import argv

script, policy = argv

private_key = 'uV3F3YluFJax1cknvbcGwgjvx4QpvB+leU8dUj2o'
input = open("..Desktop/policy.txt", "rb")
policy = input.read()
policy_encoded = base64.b64encode(policy)
signature = base64.b64encode(hmac.new(private_key, policy_encoded, sha).digest())
print "Your policy base-64 encoded is %s." % (policy_encoded)
print "Your signature base-64 encoded is %s." % (signature)
print "Your signature encoded should be 2qCp0odXe7A9IYyUVqn0w2adtCA="

JSON政策(policy.txt--UTF-8)

{ "expiration": "2007-12-01T12:00:00.000Z",
"conditions": [
{"bucket": "johnsmith"},
["starts-with", "$key", "user/eric/"],
{"acl": "public-read"},
{"success_action_redirect": "http://johnsmith.s3.amazonaws.com/successful_upload.html"},
["starts-with", "$Content-Type", "image/"],
{"x-amz-meta-uuid": "14365123651274"},
["starts-with", "$x-amz-meta-tag", ""]
]
}

1 个回答

5

我觉得问题出在你的policy.txt文件的内容上。

我从参考链接中获取了政策内容(http://doc.s3.amazonaws.com/proposals/post.html),然后把它保存为policy.txt。

{ "expiration": "2007-12-01T12:00:00.000Z",
  "conditions": [
    {"bucket": "johnsmith" },
    ["starts-with", "$key", "user/eric/"],
    {"acl": "public-read" },
    {"redirect": "http://johnsmith.s3.amazonaws.com/successful_upload.html" },
    ["starts-with", "$Content-Type", "image/"],
    {"x-amz-meta-uuid": "14365123651274"},
    ["starts-with", "$x-amz-meta-tag", ""],
  ]
}

为了得到完全相同的签名,这个文件的内容必须完全一致。

作为参考,当我复制并粘贴时,得到的结果是:MD5 (policy.txt) = 5bce89d9ff799e2064c136d76bc7fc7a。

如果我使用以下脚本(和你的脚本一样,只是调整了文件名并去掉了args

#!/usr/bin/env python
# -*- coding: utf-8 -*-

import base64, hmac, sha

private_key = 'uV3F3YluFJax1cknvbcGwgjvx4QpvB+leU8dUj2o'
input = open("policy.txt", "rb")
policy = input.read()
policy_encoded = base64.b64encode(policy)
signature = base64.b64encode(hmac.new(private_key, policy_encoded, sha).digest())
print "Your policy base-64 encoded is %s." % (policy_encoded)
print "Your signature base-64 encoded is %s." % (signature)
print "Your signature encoded should be 2qCp0odXe7A9IYyUVqn0w2adtCA="

我得到的输出是:

Your policy base-64 encoded is
eyAiZXhwaXJhdGlvbiI6ICIyMDA3LTEyLTAxVDEyOjAwOjAwLjAwMFoiLAogICJjb25kaXRpb25zIjo
gWwogICAgeyJidWNrZXQiOiAiam9obnNtaXRoIiB9LAogICAgWyJzdGFydHMtd2l0aCIsICIka2V5Ii
wgInVzZXIvZXJpYy8iXSwKICAgIHsiYWNsIjogInB1YmxpYy1yZWFkIiB9LAogICAgeyJyZWRpcmVjd
CI6ICJodHRwOi8vam9obnNtaXRoLnMzLmFtYXpvbmF3cy5jb20vc3VjY2Vzc2Z1bF91cGxvYWQuaHRt
bCIgfSwKICAgIFsic3RhcnRzLXdpdGgiLCAiJENvbnRlbnQtVHlwZSIsICJpbWFnZS8iXSwKICAgIHs
ieC1hbXotbWV0YS11dWlkIjogIjE0MzY1MTIzNjUxMjc0In0sCiAgICBbInN0YXJ0cy13aXRoIiwgIi
R4LWFtei1tZXRhLXRhZyIsICIiXSwKICBdCn0K
Your signature base-64 encoded is 2qCp0odXe7A9IYyUVqn0w2adtCA=
Your signature encoded should be 2qCp0odXe7A9IYyUVqn0w2adtCA=

所以,你的代码是可以工作的,我只是觉得你签署的政策有点不同(可能是空格的差异)。

撰写回答