最近更新时间:2017-12-21 21:20:09
金山云Openapi签名算法使用与aws openAPI签名算法向下兼容的Signature Version 4算法。出于安全考虑,大多数的金山云openAPI请求都必须使用账户密钥(包括Access Key和Secret Key)进行签名。为了方便使用者测试,推荐使用Postman的AWS Signature进行测试。
在第一次使用金山云openAPI之前,用户需要登录金山云IAM控制台上获取账户密钥。
账户密钥主要由两部分组成:
Access Key: 账户密钥的唯一表示,可以在公网进行传递。
注意:账户密钥是金山云用户的重要资产,请妥善保管。
一个原始的请求如下:
GET HTTP/1.1Content-Type: application/x-www-form-urlencodedHost: iam.api.ksyun.comX-Amz-Date: 20170621T075413Z
您可使用 Authorization 标头将身份验证信息添加到请求中。尽管该 HTTP 标头名为 Authorization,但签名信息实际上是用于身份验证的,目的是确定请求方。
Authorization标头包含以下信息:
用户签名的算法(AWS4-HMAC-SHA256)
凭证范围(包含您的访问Access Key)
已签名的标头的列表
以下是添加了签名信息的请求:
GET HTTP/1.1
Content-Type: application/x-www-form-urlencoded
Host: iam.api.ksyun.com
X-Amz-Date: 20170621T075413Z
Authorization: AWS4-HMAC-SHA256 Credential=AKLTc0PV6LmgSIu0hncDo6sR4w/20170621/cn-shanghai-3/iam/aws4_request, SignedHeaders=content-type;host;x-amz-date, Signature=cfd799ed7f29203290c6382d1001b56e316561631d7eb120b556c0e4a6e753c0
将请求的内容(主机、操作、标头等)组织为标准(规范)格式。规范请求是用于创建待签字符串的输入之一。
规范请求代码:
$CanonicalRequest = "$HTTPRequestMethod\n$CanonicalURI\n$CanonicalQueryString\n$CanonicalHeaders\n$SignedHeaders" . bin2hex(hash("sha256", $RequestPayload));
以下述请求为例:
GET HTTP/1.1
Content-Type: application/x-www-form-urlencoded
Host: iam.api.ksyun.com
X-Amz-Date: 20170621T075413Z
$HTTPRequestMethod是指HTTP的请求方法,如:GET、PUT、POST等。此请求方法是:GET
$CanonicalURI是指规范化后的HTTP的URI绝对路径,如果绝对路径为空,则使用正斜杠(/)。规范化即为根据RFC 3986标准化URI路径的过程。移除冗余部分,路径中的每个部分都必须为URI编码。上述$CanonicalURI为:/
要构建规范的请求字符串步骤如下:
a. 按字符代码点以升序顺序对参数名称进行排序。例如,以大写字母 F 开头的参数名称排在以小写字母 b 开头的参数名称之前。
b.根据以下规则对每个参数名称和值进行 URI 编码:
i. 请勿对 RFC 3986 定义的任何非预留字符进行 URI 编码,这些字符包括:A-Za-z0-9-_~.
ii. 使用%XY对其他所有字符进行百分比编码,X Y为十六进制字符(0-9A-F)
c. 以排序后的列表中第一个参数名称开头,构造规范查询字符串。
d. 对于每个参数,追加 URI 编码的参数名称,后跟等号字符 (=),再接 URI 编码的参数值。对没有值的参数使 用空字符串。
e. 在每个参数值后追加与字符 (&),列表中最后一个值除外。
规范化的过程如下:
a. 首先规范化头至少需要包含host这个标头。
b. 请将所有标头名称转换为小写形式并删除前导空格和尾随空格。将标头值中的连续空格转换为单个空格。
c. 以标头的名称进行字母排序。如果同标头的名存在多个值,对值进行排序并且用逗号(,)连接。将标头的名称与值用冒号(:)连接。
d. 将c步骤构建出的结构,用换行符(n)进行连接构建成$CanonicalHeaders(列表最后也需要增加换行符)
$SignedHeaders是指的参加签名的header列表。上述$CanonicalHeaders为content-type;host;x-amz-date
$RequestPayload为HTTP的请求body的。如果body为空那么就是空字符串。上述计算结果为:e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855
使用规范请求和额外信息(例如算法、请求日期、凭证范围和规范请求的摘要(哈希))创建待签字符串。
待签字符串计算方式如下:
$StrToSign="AWS4-HMAC-SHA256\n$RequestDateTime\n$CredentialScope\n$HashedCanonicalRequest";
$RequestDateTime代表的是请求的时间(时间格式为"Ymd\THis\Z"),例如20150830T123600Z
$CredentialScope此值是一个字符串,包含日期、目标区域、所请求的服务和小写字符形式的终止字符串(“aws4_request”)。例如:20150830\/cn-beijing-6/iam/aws4__request
使用 AWS 秘密访问密钥作为初始哈希操作的密钥,对请求日期、区域和服务执行一系列加密哈希操作,从而派生签名密钥。
待签字符串是通过账户加密密钥、请求时间(精确到天)、请求region、请求业务迭代计算而来。
其代码逻辑如下:
$secretKey = 'This is sk';
$d = '20150830';
$r = 'cn-beijing-6';
$s = 'iam';$date = hash_hmac('sha256', 'AWS4$secretKey', $d);
$region = hash_hmac('sha256', $date, $r);
$service = hash_hmac('sha256', $region, $s);
$signKey = hash_hmac('sha256', $service, 'aws4_request');
在派生签名密钥后,通过对待签字符串执行加密哈希操作来计算签名。使用派生的签名密钥作为此操作的哈希密钥。
计算签名的结果逻辑如下:
$Signature = hash_hmac('sha256', $StrToSign, $signKey);
在计算签名后,将其添加到请求的 HTTP 标头。通过将签名信息添加到名为 Authorization 的 HTTP 标头,可以包括签名信息。此标头内容是在按前面的步骤所述计算签名之后创建的,因此 Authorization 标头未包含在已签名标头的列表中。尽管此标头名为 Authorization,但签名信息实际上用于身份验证。
其代码逻辑如下:
Authorization: AWS4-HMAC-SHA256Credential=$Accesskey/$CredentialScope, SignedHeaders=$SignedHeaders, Signature=$Signature
$accesskey为账户的access key(与签名过程使用的secret key匹配的access key)
$CredentialScope,$SignedHeaders,$Signature和上述描述中的$CredentialScope,$SignedHeaders,$Signature保持一致
Authorization:AWS4-HMAC-SHA256 Credential=AKIDEXAMPLE/20150830/cn-beijing-6/iam/aws4_request,SignedHeaders=content-type;host;x-amz-date,Signature=5d672d79c15b13162d9279b0855cfba6789a8edb4c82c400e06b5924a6f2b5d7
主要SDK:
其他语言签名算法参考: