You need to enable JavaScript to run this app.
导航

签名方法

最近更新时间2023.02.10 20:00:02

首次发布时间2023.02.10 20:00:02

为什么需要签名?

为了保证请求者身份的合法性以及请求在传输过程中不被恶意篡改,火山引擎签名机制要求请求者对请求参数进行哈希值计算,经过加密后同API请求一起发送到服务器中,服务器将以同样的机制对收到的请求进行签名计算,并以此与请求者传来的签名进行比对,若签名未通过验证,请求将被拒绝。

如何计算签名?

火山引擎当前提供两种计算签名方式:
方式一:查看以下签名流程,通过编码进行签名计算;
方式二:使用封装了签名方法的SDK,SDK地址为https://github.com/volcengine。
未来我们将提供**API Explorer等更多工具方便您对API进行调试,敬请期待。

前置准备

1. 完成实名认证
2. 开通需要使用的产品服务;
3. 获取密钥(Access Key)
4. 前往产品文档中查看接口文档。

1. 创建一个正规化请求

在签名之前,首先要将请求正规化,目的是让签名计算过程无异议,其主要过程及伪代码如下:

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

Hash代指SHA256算法,HexEncode代指转16进制编码,Hmac指代Hmac_SHA256

涉及到的字段如下:

字段解释
HTTPRequestMethod指代http请求的method,例如:GET、POST等。
CanonicalURI指代正规化后的URI。如果URI为空,那么使用"/"作为绝对路径。在火山引擎中绝大多数接口的URI都为"/"。如果是复杂的path,请通过RFC3986规范进行编码。

CanonicalQueryString

指代正规化后的Query String。对于Query String的正规化大致的过程如下:

  • urlencode(注:同RFC3986方法)每一个querystring参数名称和参数值。

  • 按照ASCII字节顺序对参数名称严格排序,相同参数名的不同参数值需保持请求的原始顺序。

  • 将排序好的参数名称和参数值用=连接,按照排序结果将“参数对”用&连接。例如:CanonicalQueryString = "Action=ListUsers&Version=2018-01-01"

CanonicalHeaders

指代正规化后的header。其中伪代码如下:
CanonicalHeaders = CanonicalHeadersEntry0 + CanonicalHeadersEntry1 + ... + CanonicalHeadersEntryN
其中CanonicalHeadersEntry = Lowercase(HeaderName) + ':' + Trimall(HeaderValue) + '\n'
Lowcase代表将Header的名称全部转化成小写,Trimall表示去掉Header的值的前后多余的空格。
特别注意:最后需要添加"\n"的换行符,header的顺序是以headerName的小写后ascii排序。

SignedHeaders

指参与签名的header,和CanonicalHeaders包含的header是一一对应的,目的是指明哪些header参与签名计算,从而忽略请求被proxy添加的额外header,其中host、x-date如果存在header中则必选参与,伪代码如下:
SignedHeaders = Lowercase(HeaderName0) + ';' + Lowercase(HeaderName1) + ";" + ... + Lowercase(HeaderNameN)

RequestPayload指代完整的请求的body。

2. 创建签名字符串

签名字符串主要包含请求以及正规化请求的元数据信息,由签名算法、请求日期、信任状和正规化请求哈希值连接组成,伪代码如下:

StringToSign = Algorithm + '\n' + RequestDate + '\n' + CredentialScope + '\n' + HexEncode(Hash(CanonicalRequest))

涉及到的字段如下

字段解释
Algorithm指代签名的算法,目前火山引擎仅支持HMAC-SHA256的签名算法。
RequestDate指代请求UTC时间,即请求头公共参数中X-Date的取值,请使用格式:YYYYMMDD'T'HHMMSS'Z' ,例如:20201103T104027Z
CredentialScope指代信任状,格式为:YYYYMMDD/region/service/request
CanonicalRequest指代上一小节正规化请求的结果。

3. 计算签名秘钥(signing-key)

在计算签名前,首先从私有访问密钥(Secret Access Key)派生出签名密钥(signing key),而不是直接使用私有访问密钥。具体计算过程如下:

kSecret = *Your Secret Access Key*
kDate = HMAC(kSecret, Date)
kRegion = HMAC(kDate, Region)
kService = HMAC(kRegion, Service)
kSigning = HMAC(kService, "request")

其中Date精确到日,与RequestDate中YYYYMMDD部分相同。

4. 计算签名

Signature = HexEncode(HMAC(kSigning, StringToSign))

然后构建header

Authorization: HMAC-SHA256 Credential={AccessKeyId}/{CredentialScope}, SignedHeaders={SignedHeaders}, Signature={Signature}

表达式中用{}括起来的代表上文计算出的中间过程。

签名示例

以请求IAM的接口为例,示例中Access Key不具备权限,仅作demo示范,实际请求请使用真实创建的Access Key

Access Key ID:

AKLTMjI2ODVlYzI3ZGY1NGU4ZjhjYWRjMTlmNTM5OTZkYzE

Secret Access Key:

TnpCak5XWXpZV1U0WkRaaE5ERmxaR0ZpTmpjeVkyUXlZek0wTWpJMU1qWQ==

原始请求为:

GET https://iam.volcengineapi.com/?Action=ListUsers&Version=2018-01-01&Limit=10&Offset=0 HTTP/1.1
Host: iam.volcengineapi.com
Content-Type: application/x-www-form-urlencoded; charset=utf-8
X-Content-Sha256:e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855
X-Date:20201230T081805Z

签名过程如下:

任务1:创建规范请求

规范请求如下

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

HTTPRequestMethod

GET

CanonicalURI

/

CanonicalQueryString

Action=ListUsers&Limit=10&Offset=0&Version=2018-01-01

CanonicalHeaders
将需要参与签名的header的key全部转成小写, 然后以ASCII排序后以key-value的方式组合后换行构建。

content-type:application/x-www-form-urlencoded; charset=utf-8
host:iam.volcengineapi.com
x-content-sha256:e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855
x-date:20201230T081805Z
// 多一个换行

SignedHeaders

content-type;host;x-content-sha256;x-date

HexEncode(Hash(RequestPayload))
无论是GET请求还是POST请求都有RequestPayload,其中此请求中的RequestPayload是空字符串。
这里的hash算法代指:sha****256 []byte

e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855

最终CanonicalRequest

GET
/
Action=ListUsers&Limit=10&Offset=0&Version=2018-01-01
content-type:application/x-www-form-urlencoded; charset=utf-8
host:iam.volcengineapi.com
x-content-sha256:e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855
x-date:20201230T081805Z

content-type;host;x-content-sha256;x-date
e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855

任务2:创建待签字符串

StringToSign = Algorithm + '\n' + RequestDate + '\n' + CredentialScope + '\n' + HexEncode(Hash(CanonicalRequest))

Algorithm
目前是一个固定的字符串

HMAC-SHA256

RequestDate
请求发起的时间, 与X-Date相同。

20201230T081805Z

CredentialScope
指代信任状,格式为:YYYYMMDD/region/service/request
此请求信息如下:

20201230/cn-north-1/iam/request

HexEncode(Hash(CanonicalRequest))

3a4d4dee07c3308a52da01bc12d7a83c3705bfa543f51648f46de880bb2a7447

最终StringToSign

HMAC-SHA256
20201230T081805Z
20201230/cn-north-1/iam/request
3a4d4dee07c3308a52da01bc12d7a83c3705bfa543f51648f46de880bb2a7447

任务3:构建签名

HMAC这里代指HMAC-SHA256

Signingkey示例

HMAC(HMAC(HMAC(HMAC(kSecret,"20201230"),"cn-north-1"),"iam"),"request")

以下示例显示了此 HMAC 哈希操作序列生成的派生签名密钥。这说明了此二进制签名密钥中每个字节的十六进制表示形式。

e7d2eb478084eaaaf8f85c161de16f13d97e52e77bd0415f33e7feb561cccffd

Signature示例

signature = HexEncode(HMAC(Signingkey, StringToSign))

最终的结果如下:

28eeabbbd726b87002e0fe58ad8c1c768e619b06e2646f35b6ad7ed029a6d8a7

任务4:将签名添加到请求当中

在请求中增加Authorization的header如下:

Authorization: HMAC-SHA256 Credential={AccessKeyId}/{CredentialScope}, SignedHeaders={SignedHeaders}, Signature={Signature}

完整结果如下:

Authorization: HMAC-SHA256 Credential=AKLTMjI2ODVlYzI3ZGY1NGU4ZjhjYWRjMTlmNTM5OTZkYzE/20201230/cn-north-1/iam/request, SignedHeaders=content-type;host;x-content-sha256;x-date, Signature=28eeabbbd726b87002e0fe58ad8c1c768e619b06e2646f35b6ad7ed029a6d8a7