签名方法
您在使用 API 时,需要对请求进行签名。要计算签名,首先要将选择的请求元素连接形成一个字符串,称为待签名字符串。然后,您可以使用签名密钥来计算待签字符串的 HMAC 散列消息认证码。
下图展示了签名的计算过程:
签名方法与 AWS4 签名方法类似,仅需将 AWS4 替换为 SD1 即可。
下表介绍了图中显示的函数。您需要为这些函数实现相应的代码。
函数 | 描述 |
---|---|
Lowercase() | 将字符串转换为小写。 |
Hex() | base-16 编码的小写形式。 |
SHA256Hash() | 安全哈希算法(SHA)加密哈希函数。 |
HMAC-SHA256() | 使用 SHA256 算法和提供的签名密钥计算 HMAC。这是最终的签名。 |
Trim() | 删除所有前导空格或尾随空格。 |
UriEncode() | URI 对每个字节进行编码,必须遵循 RFC 3986 中的规则。 |
签名步骤
规范化 HTTP 请求头
发送请求的 HTTP 方法,例如 GET 或者 POST,非大写的方法需要转换为大写。
规范化 URL 路径
绝对路径组件 URI 的 URI 编码版本,以域名后面的 /
开头,直至字符串结尾处,或者如果包含查询字符串参数,则直至问号字符 ?
如果绝对路径为空,则使用正斜杠字符 /
。
例如:https://api.example.com/api/v1/example
的 URI 路径为 /api/v1/example=example
而编译后的 URI 路径为 /api/v1/example%3Dexample
。
如果绝对路径为空,则使用正斜杠字符 /
。
规范化查询字符串
URI 编码的查询字符串参数。您需要单独对每个名称和值进行 URI 编码。
例如:https://api.example.com/api/v1/example?name=value&name2=value2
的查询字符串为 name=value&name2=value2
。
需要对每个请求参数的名称和值进行URL编码,名称和值要按照 RFC3986 规则进行编码。编码规则如下:
- 字符 A~Z、a~z、0~9 以及字符
-
_
.
不编码 - 其他字符编码成
%XY
的形式,其中 XY 是字符的 ASCII 码的十六进制表示。例如:#
编码成%23
- 空格编码成
%20
,而不是+
在对参数和值编码后,将它们用 =
进行连接,然后用 &
连接所有的查询字符串。
例如:name=!value&name|2=value2
进行编码后为 name=%21value&name%7C2=value2
。
如果 URI 不包含 ?
,则请求中没有查询字符串,并且需要将规范查询字符串设置为空字符串,您仍然需要包含换行符 \n
。
规范化请求头
将请求头的名称转换为小写,去除前后的空格。请求头的值也要去除前后的空格。 按照 key:value
格式拼接。然后按照名称的字母顺序对请求头的 key
进行升序排序,并用 \n
连接所有头。
签名中必须包含 host
标头(对于 HTTP/1.1
)或 :authority
标头(对于 HTTP/2
)以及任何 x-sd-*
标头。签名中也可以包含其他标准标头,例如 content-type
。
必填的 x-sd-*
标头如下:
x-sd-api-version
: API 版本号,目前支持1.0
x-sd-datetime
: 请求的日期和时间,必须遵守 ISO 8601 格式,例如20240101T173850Z
x-sd-instance-id
: 服务实例 ID,用于标识服务实例,例如12345678-1234-1234-1234-1234567890ab
例如现在有以下头:
Host: api.example.com
X-SD-Api-Version: 1.0
X-SD-Datetime: 20240101T173850Z
X-SD-Instance-Id: 12345678-1234-1234-1234-1234567890ab
经过规范化后为(\n
为换行符):
host:api.example.com \n
x-sd-api-version:1.0 \n
x-sd-datetime:20240101T173850Z \n
x-sd-instance-id:12345678-1234-1234-1234-1234567890ab
推荐加上所有的请求头,以便更好的验证请求的合法性。
创建规范请求的哈希值
使用创建负载的哈希时所使用的相同算法来创建规范请求的哈希,经过哈希处理的规范请求必须以小写十六进制字符串形式表示。
注意:当负载包含文件时,不需要对文件进行哈希处理,直接跳过文件这一项
拼接待签名字符串
要创建待签字符串,请串联以下由换行符分隔的以下字符串(\n
为换行符):
Algorithm \n
RequestDateTime \n
CredentialScope \n
HashedCanonicalRequest
Algorithm
:签名算法,对于 SHA-256,算法是SD1-HMAC-SHA256
RequestDateTime
:请求的日期和时间,该值是采用 ISO 8601 格式的当前 UTC 时间,例如20240101T173850Z
CredentialScope
:凭证范围,格式为YYYYMMDD/region/service/SD1_request
HashedCanonicalRequest
:上一步中计算出的规范请求的哈希
region枚举:sd-region
service枚举:sd-service
例如:
"SD1-HMAC-SHA256" + "\n" +
"20240101T173850Z" + "\n" +
"20240101/ap-east-1/service/sd1_request" + "\n" +
"1234567890abcdef1234567890abcdef1234567890abcdef1234567890abcdef"
创建签名密钥
要创建签名密钥,请使用秘密访问密钥作为初始哈希操作的密钥,对请求日期、区域和服务执行一系列加密哈希操作。
对于每个步骤,使用所需的密匙和数据调用哈希函数,每次调用哈希函数的结果都会变成下一次调用哈希函数的输入。
以下示例说明了如何创建本过程下一部分中使用的 SigningKey,并说明了输入的串联和哈希顺序。HMAC-SHA256
是用于对数据进行哈希处理的哈希功能。
DateKey = HMAC-SHA256("SD1"+"<SecretAccessKey>", "<YYYYMMDD>")
DateRegionKey = HMAC-SHA256(<DateKey>, "<sd-region>")
DateRegionServiceKey = HMAC-SHA256(<DateRegionKey>, "<sd-service>")
SigningKey = HMAC-SHA256(<DateRegionServiceKey>, "sd1_request")
SecretAccessKey
:秘密访问密钥YYYYMMDD
:请求日期,格式为YYYYMMDD
,例如20240101
sd-region
:区域,例如ap-east-1
sd-service
:服务,例如image-moderation
计算签名
创建签名密钥后,通过对待签字符串执行加密哈希操作来计算签名,使用创建的签名密钥作为此操作的哈希密钥。
Signature = Hex(HMAC-SHA256(SigningKey, StringToSign))
将签名添加至请求
将计算出的签名添加到您的请求中。
将签名放入 Authorization
标头中,,
两侧没有空格,例如:
Authorization: SD1-HMAC-SHA256 Credential=012345ABCDEFGHJKLNMOPQRSTU/20240101/ap-east-1/service/sd1_request,
SignedHeaders=host;x-sd-api-version;x-sd-datetime,x-sd-instance-id,
Signature=1234567890abcdef1234567890abcdef1234567890abcdef1234567890abcdef