我正在用 python 设计一个 RESTful API。我想使用 HMAC 身份验证。我找不到任何合适的 HMAC 库,所以我自己动手。但是,我想使用众所周知的标准,例如AWS HMAC authentication v4。
在编写符合 AWS 的客户端和服务器 HMAC 身份验证实施时,我注意到该标准设计的一些不常见的方面。我未能完全掌握所做的几个设计选择。
问题 1:为什么 AWS 使用复杂的签名密钥(通过 HMAC 生成)而不是共享密钥本身?
在计算签名之前,您从您的 AWS 秘密访问密钥派生一个签名密钥。(您不只是使用您的秘密访问密钥对请求进行签名。)然后您使用签名密钥和您在任务 2 中创建的字符串进行签名:为签名版本 4 创建要签名的字符串作为密钥的输入哈希函数。来自键控散列函数的十六进制编码结果是签名。
计算签名
派生您的签名密钥。为此,您使用您的秘密访问密钥创建一系列基于哈希的消息身份验证代码 (HMAC),如以下伪代码所示,其中 HMAC(key, data) 表示以二进制格式返回输出的 HMAC-SHA256 函数. 每个哈希函数的结果成为下一个哈希函数的输入。
用于派生签名密钥的伪代码:
kSecret = Your AWS Secret Access Key
kDate = HMAC("AWS4" + kSecret, Date)
kRegion = HMAC(kDate, Region)
kService = HMAC(kRegion, Service)
kSigning = HMAC(kService, "aws4_request")
问题 2:我不明白“凭据范围”字符串的用途。
在任务 2 (为签名版本 4 创建要签名的字符串)的步骤 2-3 中,将日期和凭据范围值附加到已签名的字符串中。这些价值观的目的是什么?
该标准已经在x-amz-date标头中签署了 UTC 时间戳,作为在任务 1 中准备的规范请求的一部分。区域说明符 (us-east-1) 也是如此,因为它可能应该反映在Host:标头中。
附加请求日期值,后跟换行符。日期通过 YYYYMMDD'T'HHMMSS'Z' 格式的 x-amz-date 标头使用 ISO8601 基本格式指定。此值必须与您在之前的任何步骤中使用的值相匹配。
20110909T233600Z\n
附加凭证范围值,后跟换行符。此值是一个字符串,其中包含日期(只是日期,而不是日期和时间)、目标区域、请求的服务以及小写字符的终止字符串 ("aws4_request")。区域和服务名称字符串必须采用 UTF-8 编码。
20110909/us-east-1/iam/aws4_request\n
日期必须采用 YYYYMMDD 格式。请注意,日期不包括时间值。