全部文档
当前文档

暂无内容

如果没有找到您期望的内容,请尝试其他搜索词

文档中心

签名机制

最近更新时间:2023-09-04 17:01:12

签名机制

金山云OpenAPI支持一种签名算法:AWS签名算法版本4,您可以根据业务需要选择所使用的签名算法,请注意两种签名算法所使用的公共参数有所区别。

AWS签名算法版本4

支持GET和POST两种HTTP方法,GET方法所有请求参数包括signature放置在url中,POST方法则将signature以名为Authorization header的形式放置在header中,其主要区别在于GET方式处理的请求url长度不能过长。

签名计算的主要流程如下:

1、创建一个正规化请求

在签名前,首先将请求进行正规化格式化,目的是让签名计算过程无二意,其主要过程伪代码如下:

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

Hash指代计算哈希的算法,目前使用SHA-256,HexEncode是对哈希值进行用16进制编码(使用小写字母)。

具体步骤如下

  1. 抽取HTTP请求方法(如GET、PUT、POST)结尾附加“换行符”
  2. URI绝对路径进行URI编码得到正规化URI,如果绝对路径为空,那么使用前斜线"/",结尾附加“换行符”
  3. 构建正规化Querystring,结尾附加“换行符”
    • URI编码每一个querystring参数名称和参数值(注:GET方式需要包含哈希算法、信任状、签名日期和签名header等全部参数)
    • 按照ASCII字节顺序对参数名称严格排序
    • 将排序好的参数名称和参数值用=连接,按照排序结果将“参数对”用&连接
  4. 构建正规化headers,结尾附加“换行符”,伪代码如下:
CanonicalHeaders = CanonicalHeadersEntry0 + CanonicalHeadersEntry1 + ... + CanonicalHeadersEntryN

其中:

CanonicalHeadersEntry = Lowercase(HeaderName) + ':' + Trimall(HeaderValue) + '\n'

lowercase表示将header名字转为小写字母,trimall表示去掉header值前和值后的白空格,并将header值里面的连续白空格变成单空格,但是不去掉双引号中间的任何空格,且最后的正规化headers是按照header名称排序后的结果。

建议采用的CanonicalHeaders 如下:

CanonicalHeaders = 'host:' + host + '\n' + 'x-amz-date:' + RequestDate  + '\n'

其中,
RequestDate是公共请求头X-Amz-Date的值,表示当前请求的时间和日期,格式YYYYMMDD’T’HHMMSS’Z’ ,例如:20210726T111901Z

  1. 添加签名headers,结尾附加“换行符”。签名header是包含在正规化headers中名称列表,其目的是指明哪些header参与签名计算,从而忽略请求被proxy添加的额外header,其中host、x-amz-date两个header如果存在则必须添加进来,伪代码如下
SignedHeaders = Lowercase(HeaderName0) + ';' + Lowercase(HeaderName1) + ";" + ... + Lowercase(HeaderNameN)

对应上面建议的CanonicalHeaders,需采用如下的SignedHeaders :

SignedHeaders = 'host;x-amz-date'

然后处理请求body,如下
6. 对请求body使用哈希算法(SHA256)计算哈希值,并将二进制哈希值结果用16进制编码表示出来(且不使用大写字符),伪代码如下:

HashedPayload = Lowercase(HexEncode(Hash(requestPayload)))
  1. 此时,将上述1-6步骤的结果连接成一个字符串,即为正规化请求(CanonicalRequest)
  2. 对第7步的正规化请求使用哈希算法(SHA256)计算哈希值,并将二进制哈希值结果用16进制编码表示出来(且不使用大写字符),伪代码如下:
HashedCanonicalRequest = Lowercase(HexEncode(Hash(CanonicalRequest)))

2、创建签名字符串

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

StringToSign = Algorithm + '\n' + RequestDate + '\n' + CredentialScope + '\n' + HashedCanonicalRequest

其中,
签名算法(Algorithm)为AWS4-HMAC-SHA256;
请求日期(RequestDate)是公共请求头X-Amz-Date的值,表示当前请求的日期和时间,格式YYYYMMDD’T’HHMMSS’Z’ ,例如:20210726T111901Z;
信任状(CredentialScope)格式为;YYYYMMDD/Region/Service/aws4_request;
正规化请求哈希值(HashedCanonicalRequest )为上述1中第8步的结果(注意结尾不附加“换行符”)。

注意:
YYYYMMDD取自RequestDate中的日期,对应上面的示例为20210726
Region为cn-beijing-6
Service为cdn

3、计算签名信息

在计算签名前,首先从私有访问密钥(secret AccessKey)派生出签名密钥(signing key),而不是直接使用私有访问密钥;之后使用签名密钥和2中计算的签名字符串来计算签名值,具体计算过程如下

  1. 生成签名密钥,伪代码如下
kSecret = *Your KSC Secret Access Key*
kDate = HMAC("AWS4" + kSecret, Date)
kRegion = HMAC(kDate, Region)
kService = HMAC(kRegion, Service)
kSigning = HMAC(kService, "aws4_request")

其方式是通过HMAC算法依次生成下一个HMAC的key值(第一个为私有访问密钥字符串),而message值则依次为信任状中的各项内容(Date、Region、Service、字符串"aws4_request");HMAC算法采用HMAC-SHA256,返回值为哈希值二进制形式(256bit,32字节),不需要做8/16进制编码显示。

注意:
Date为YYYYMMDD,取自RequestDate中的日期,对应上面的示例为20210726
Region为cn-beijing-6
Service为cdn

  1. 计算签名,伪代码如下:
signature = HexEncode(HMAC(derived-signing-key, string-to-sign))

使用HMAC-SHA256算法,以签名密钥作为key,签名字符串作为data计算签名,签名后的二进制哈希值结果以16进制编码输出。

4、签名的请求示例

通过 RESTful API 对 CDN 发起的 HTTP 签名请求,可以通过以下方式传递签名:

通过标准的 HTTP Authorization 头

签名头格式如下:

Authorization: Algorithm + ' ' + 'Credential=' + AccessKeyID + '/' + CredentialScope + ', ' +   'SignedHeaders=' + SignedHeaders + ', ' + 'Signature=' + signature

其中,
Algorithm为AWS4-HMAC-SHA256;
AccessKeyID为访问密钥ID;
CredentialScope格式为YYYYMMDD/Region/Service/aws4_request;
SignedHeaders为签名headers,取值如上所述
signature为签名值,取值如上所述

注意:
YYYYMMDD取自RequestDate中的日期,对应上面的示例为20210726
Region为cn-beijing-6
Service为cdn

GET请求示例:

GET /2016-09-01/domain/GetDomainConfigs?DomainId=2D08BTW HTTP/1.1
User-Agent: python-requests/2.23.0
accept-encoding: gzip
accept: */*
connection: keep-alive
host: cdn.api.ksyun.com
x-action: GetDomainConfigs
x-version: 2016-09-01
x-amz-date: 20210726T111902Z
Authorization: AWS4-HMAC-SHA256 Credential=LVLBPx7VDwlJRQGkpODXBCCruZ/20210726/cn-beijing-6/cdn/aws4_request, SignedHeaders=host;x-amz-date, Signature=cef04283a6cd6babf04x7f1ab132xq0ac7cd7q81537beqedbd4d9495f8a8axe3

POST请求示例:

POST /2016-09-01/domain/GetDomainConfigs HTTP/1.1
Host: cdn.api.ksyun.com
User-Agent: python-requests/2.23.0
Accept-Encoding: gzip, deflate
Accept: application/json
Connection: keep-alive
content-type: application/json
x-amz-date: 20210726T111901Z
authorization: AWS4-HMAC-SHA256 Credential=LVLBPx7VDwlJRQGkpODXBCCruZ/20210726/cn-shanghai-1/cdn/aws4_request, SignedHeaders=content-type;host;x-amz-date, Signature=cef04283a6cd6babf04x7f1ab132xq0ac7cd7q81537beqedbd4d9495f8a8axe3
X-version: 2016-09-01
X-action: GetDomainConfigs
Content-Length: 22

{“DomainId”:“2D08BTW”}

5、签名SDK示例

主要SDK:

PHP

JAVA

PYTHON

其他语言签名算法参考:

GOLANG

JS

文档导读
纯净模式常规模式

纯净模式

点击可全屏预览文档内容
文档反馈