签名机制

OpenAPI 仅支持 JSON 格式数据。

所有请求中,鉴权信息通过 Authorization HTTP Header 提供。如下:

Authorization: WEKEY-HMAC-SHA256 host;x-wekey-date,fe5f80f77445342fe2855ddc963176630326f102d5fa3beca038a248ff027d04

整个头信息分三部分:

  1. 签名算法:WEKEY-HMAC-SHA256
  2. 参与签名 Header(转小写升序排列):host;x-wekey-date
  3. 签名结果:fe5f80f77445342fe2855ddc963176630326f102d5fa3beca038a248ff027d04

签名步骤

创建 Canonical Request

创建 canonical request 伪代码

CanonicalRequest =
  HTTPRequestMethod + '\n' +
  CanonicalURI + '\n' +
  CanonicalQueryString + '\n' +
  CanonicalHeaders + '\n' +
  SignedHeaders + '\n' +
  HexEncode(Hash(RequestPayload))

Hash 为摘要算法,通常为 SHA-256。HexEncode 表示一个函数,该函数以小写字符返回摘要的 base-16 编码。例如,HexEncode(“m”) 返回值 6d 而不是 6D。

举个例子

GET https://me.wekey.com/ta-wekey-dash/users?page=1&size=10& HTTP/1.1
Host: me.wekey.com
Content-Type: application/x-www-form-urlencoded; charset=utf-8
X-Wekey-Date: 20150830T123600Z

要创建 canonical request,请按照以下步骤拼接字符串:

1、HTTP 请求方法(GET、PUT、DELETE)开头,后跟换行符。

GET

2、规范 url path,后跟换行符。

/ta-wekey-dash/users

如果 path 为空,请使用正斜杠(/)。

3、规范 url query,后跟换行符。如果不包含查询字符串,请使用空字符串。

page=1&size=10

要构造规范查询字符串,请按照以下步骤:

  1. 将字符串通过参数名称升序排序。如果具有重复名称的参数应按值排序。如,以大写字母 F 开头的参数名

  2. 称位于小写字母 b 开头的参数名称之前。 将所有参数进行 urlencode 编码。

  3. 规范 header,后跟换行符。

对于 HTTP/1.1 请求,至少必须包含 host header。对于其它的标准 header,如 content-type 是可选的。不同服务有不同要求。

示范规范 header:

content-type:application/x-www-form-urlencoded; charset=utf-8\n
host:me.wekey.com\n
x-wekey-date:20150830T123600Z\n

要创建规范标题列表哦,请将所有 header 名称转换为小写并删除首尾空格。将 header 中的连续空格转换为单个空格。

以下伪代码描述了如何构造规范的 header 列表:

CanonicalHeaders =
CanonicalHeadersEntry0 + CanonicalHeadersEntry1 + ... + CanonicalHeadersEntryN
CanonicalHeadersEntry =
Lowercase(HeaderName) + ':' + Trimall(HeaderValue) + '\n'

Lowercase 表示将所有字符转换为小写的函数。该 Trimall 函数删除值前后多余的空格,并将连续空格转换为单个空格。

通过按字符代码对(小写)header 进行排序,然后遍历标题名称来构建规范标题列表。根据以下规则构造每个标头:

  • 附加小写标题名称,后跟冒号。
  • 为该标头附加一个逗号分隔的值列表。不要对具有多个值的标题中的值进行排序。
  • 追加新行 (' \n')。

以下示例将一组更复杂的标头与其规范形式进行了比较:

示例原始 header

Host:me.wekey.com\n
Content-Type:application/x-www-form-urlencoded; charset=utf-8\n
My-header1:    a   b   c  \n
X-Wekey-Date:20150830T123600Z\n
My-Header2:    "a   b   c"  \n

示范规范形式

content-type:application/x-www-form-urlencoded; charset=utf-8\n
host:me.wekey.com\n
my-header1:a b c\n
my-header2:"a b c"\n
x-wekey-date:20150830T123600Z\n

笔记 每个标题后跟一个换行符,这意味着完整列表以换行符结尾。

5、签名的 header,后跟换行符。

SignedHeaders =
Lowercase(HeaderName0) + ';' + Lowercase(HeaderName1) + ";" + ... + Lowercase(HeaderNameN)

通过迭代标头名称集合来构建签名标头列表,按小写字符代码排序。对于除最后一个以外的每个标题名称,将分号 (';') 附加到标题名称以将其与以下标题名称分开。

示例签名标头

content-type;host;x-wekey-date\n

6、使用 SHA256 之类的散列(摘要)函数从 HTTP 或 HTTPS 请求正文中的负载创建散列值。

示例结构

HashedPayload = Lowercase(HexEncode(Hash(requestPayload)))

创建要签名的字符串时,请指定用于散列有效负载的签名算法。例如,如果您使用 SHA256,您将指定 WEKEY-HMAC-SHA256 作为签名算法。散列后的有效负载必须表示为小写十六进制字符串。

如果有效负载为空,则使用空字符串作为散列函数的输入。在本示例中,有效负载为空。

示例哈希有效负载(空字符串)

e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855

7、要构建完成的规范请求,请将每个步骤中的所有组件组合为一个字符串。如前所述,每个组件都以换行符结尾。如果您遵循前面解释的规范请求伪代码,则生成的规范请求将显示在以下示例中。

示例规范请求

GET
/
page=1&size=10
content-type:application/x-www-form-urlencoded; charset=utf-8
host:me.wekey.com
x-wekey-date:20150830T123600Z
 
content-type;host;x-wekey-date
e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855

8、使用您用来散列有效负载的相同算法创建规范请求的摘要(散列)。

散列的规范请求必须表示为一串小写十六进制字符。以下示例显示了使用 SHA-256 对示例规范请求进行哈希处理的结果。

哈希规范请求示例

f536975d06c0309214f805bb90ccff089219ecd68b2577efef23edd43b7e1a59

创建 stringToSign

要创建要签名的字符串,请连接规范请求的算法、日期和时间、凭证范围和摘要,如以下伪代码所示:

要签名的字符串结构

StringToSign =
    Algorithm + \n +
    RequestDateTime + \n +
    CredentialScope + \n +
    HashedCanonicalRequest

以下示例显示了如何构造字符串以使用来自 创建规范请求 的相同请求进行签名。

示例 HTTPS 请求

GET https://me.wekey.com/?page=1&size=10 HTTP/1.1
Host: me.wekey.com
Content-Type: application/x-www-form-urlencoded; charset=utf-8
X-Wekey-Date: 20150830T123600Z

创建要签名的字符串

从算法名称开始,后跟换行符。此值是您用于计算规范请求中的摘要的散列算法。对于 SHA256,WEKEY-HMAC-SHA256是算法。

WEKEY-HMAC-SHA256\n

附加请求日期值,后跟换行符。x-wekey-date 日期在 YYYYMMDD’T’HHMMSS’Z' 格式的标头中使用 ISO8601 基本格式指定。此值必须与您在之前的任何步骤中使用的值相匹配。

20150830T123600Z\n

附加凭证范围值,后跟换行符。此值是一个字符串,其中至少包括模块,标识符(可为空)。区域和服务名称字符串必须采用 UTF-8 编码。

fido-server/<user_id>\n

日期必须采用YYYYMMDD格式。请注意,日期不包括时间值。

验证您指定的区域是否是您将请求发送到的区域。

附加您在创建的规范请求的哈希。此值后面没有换行符。散列的规范请求必须是小写的 base-16 编码,如RFC 4648 的第 8 节所定义.

f536975d06c0309214f805bb90ccff089219ecd68b2577efef23edd43b7e1a59

以下要签名的字符串是 2015 年 8 月 30 日对 IAM 的请求。

WEKEY-HMAC-SHA256
20150830T123600Z
fido-server/ak17ddaqw1291212
f536975d06c0309214f805bb90ccff089219ecd68b2577efef23edd43b7e1a59

计算签名 signature

将得到的 stringToSign 通过制定的算法进行签名,如 WEKEY-HMAC-SHA256,即 HMAC-SHA256:

HMAC-SHA256(secret_key, stringToSign)

得到签名:

f536975d06c0309214f805bb90ccff089219ecd68b2577efef23edd43b7e1a59

将签名添加到 HTTP 请求

其结构为:

Authorization: algorithm <access key ID>/<credential scope>,SignedHeaders,signature