Amazon Web Services
一般参考 (Version 1.0)
AWS 服务或AWS文档中描述的功能,可能因地区/位置而异。点 击 Getting Started with Amazon AWS to see specific differences applicable to the China (Beijing) Region.

说明如何为 Signature 版本 4 派生签名密钥的示例

本页以多种编程语言说明示例,介绍如何为 Signature 版本 4 派生签名密钥。此页面上的示例仅说明如何派生签名密钥,它只是 AWS 请求签名过程的一部分。有关说明整个过程的示例,请参阅完整版本 4 签名过程的示例 (Python)

注意

如果使用 AWS 开发工具包之一 (包括 适用于 Java 的开发工具包、.NET、Python、Ruby 或 JavaScript),您不必手动执行派生签名密钥和将身份验证信息添加到请求的步骤。这些软件开发工具包将为您执行这些工作。仅当您直接发出 HTTP 或 HTTPS 请求时,才需要您手动签署请求。

使用 Java 派生签名密钥

Copy
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")); } 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; }

使用 .NET (C#) 派生签名密钥

Copy
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; }

使用 Python 派生签名密钥

Copy
def sign(key, msg): return hmac.new(key, msg.encode("utf-8"), hashlib.sha256).digest() def getSignatureKey(key, dateStamp, regionName, serviceName): kDate = sign(("AWS4" + key).encode("utf-8"), dateStamp) kRegion = sign(kDate, regionName) kService = sign(kRegion, serviceName) kSigning = sign(kService, "aws4_request") return kSigning

使用 Ruby 派生签名密钥

Copy
def getSignatureKey key, dateStamp, regionName, serviceName kDate = OpenSSL::HMAC.digest('sha256', "AWS4" + key, dateStamp) kRegion = OpenSSL::HMAC.digest('sha256', kDate, regionName) kService = OpenSSL::HMAC.digest('sha256', kRegion, serviceName) kSigning = OpenSSL::HMAC.digest('sha256', kService, "aws4_request") kSigning end

使用 JavaScript 派生签名密钥

以下示例使用 crypto-js 库。有关更多信息,请参阅 https://www.npmjs.com/package/crypto-jshttps://code.google.com/archive/p/crypto-js/

Copy
var crypto = require("crypto-js"); function getSignatureKey(Crypto, key, dateStamp, regionName, serviceName) { var kDate = Crypto.HmacSHA256(dateStamp, "AWS4" + key); var kRegion = Crypto.HmacSHA256(regionName, kDate); var kService = Crypto.HmacSHA256(serviceName, kRegion); var kSigning = Crypto.HmacSHA256("aws4_request", kService); return kSigning; }

使用其他语言派生签名密钥

如果您需要用不同编程语言实施此逻辑,我们建议您使用本节中的值来测试密钥派生算法的中间步骤。以下 Ruby 示例在算法的每个步骤后使用 hexEncode 函数输出结果。

Copy
def hexEncode bindata result="" data=bindata.unpack("C*") data.each {|b| result+= "%02x" % b} result end

如果使用以下测试输入:

Copy
key = 'wJalrXUtnFEMI/K7MDENG+bPxRfiCYEXAMPLEKEY' dateStamp = '20120215' regionName = 'cn-north-1' serviceName = 'iam'

您的程序将为 getSignatureKey 中的值生成以下值。请注意,这些值是二进制数据的十六进制编码表示形式;密钥本身和中间值应该是二进制格式。

Copy
kSecret = '41575334774a616c725855746e46454d492f4b374d44454e472b62507852666943594558414d504c454b4559' kDate = '969fbb94feb542b71ede6f87fe4d5fa29c789342b0f407474670f0c2489e0a0d' kRegion = 'f5e672e58cf132b0a7ac38224ed20013b5f068e4e4de6ebc05d87f724508595e' kService = 'e2569e3d090ed691c9ef28c5fb6afbea3f759699099ad1f884a589aad97bf4ca' kSigning = '2f93fd817068852310c6054f85a5ffe1a23da3e1587e39ba922f1fac469088da'

常见编码错误

要简化您的任务,请避免下列常见编码错误。

提示

使用能显示原始 HTTP 请求的工具检查要发送给 AWS 的 HTTP 请求。这样能帮助您找到代码中并不明显的问题。

  • 不要包含多余的换行符,或忘记在必要的位置使用换行符。

  • 不要在凭证范围中不正确地设置日期格式,如使用时间戳而不是 YYYYMMDD 格式。

  • 确保规范标头和签名标头中的标头相同。

  • 不要在计算中间密钥时意外交换密钥和数据 (消息)。上一步的计算结果是密钥,而不是数据。仔细检查文档中的加密基元,确保以正确顺序放置参数。

  • 不要忘记在第一步在密钥之前添加字符串“AWS4”。如果使用 for 循环或迭代程序来实施密钥派生,不要忘记第一次迭代的特殊情况,以便包含“AWS4”字符串。

有关可能的错误的更多信息,请参阅排除 AWS Signature Version 4 错误