Skip to content

签名方法

您在使用 API 时,需要对请求进行签名。要计算签名,首先要将选择的请求元素连接形成一个字符串,称为待签名字符串。然后,您可以使用签名密钥来计算待签字符串的 HMAC 散列消息认证码。

下图展示了签名的计算过程: signature method image

签名方法与 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