CDN

签名机制

最近更新时间:2017-12-21 21:20:09

签名机制

金山云Openapi签名算法使用与aws openAPI签名算法向下兼容的Signature Version 4算法。出于安全考虑,大多数的金山云openAPI请求都必须使用账户密钥(包括Access Key和Secret Key)进行签名。为了方便使用者测试,推荐使用Postman的AWS Signature进行测试。

获取Acess Key和Secret Key

在第一次使用金山云openAPI之前,用户需要登录金山云IAM控制台上获取账户密钥。

账户密钥主要由两部分组成:

  • Access Key: 账户密钥的唯一表示,可以在公网进行传递。

  • Secret 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

签名过程

1.创建规范请求

将请求的内容(主机、操作、标头等)组织为标准(规范)格式。规范请求是用于创建待签字符串的输入之一。

规范请求代码:

$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为:/

  • $CanonicalQueryString是指规范化的请求字符串。如果不包括query string,请使用空白行代替。上述$CanonicalQueryString为:Action=ListUsers&Version=2015-11-01

要构建规范的请求字符串步骤如下:

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. 在每个参数值后追加与字符 (&),列表中最后一个值除外。

  • $CanonicalHeaders是指的规范化后的标头。 上述$CanonicalHeaders为:content-type:application/x-www-form-urlencodedhost:iam.api.ksyun.comx-amz-date:20170621T075413Z

规范化的过程如下:

a. 首先规范化头至少需要包含host这个标头。

b. 请将所有标头名称转换为小写形式并删除前导空格和尾随空格。将标头值中的连续空格转换为单个空格。

c. 以标头的名称进行字母排序。如果同标头的名存在多个值,对值进行排序并且用逗号(,)连接。将标头的名称与值用冒号(:)连接。

d. 将c步骤构建出的结构,用换行符(n)进行连接构建成$CanonicalHeaders(列表最后也需要增加换行符)

  • $SignedHeaders是指的参加签名的header列表。上述$CanonicalHeaders为content-type;host;x-amz-date

  • $RequestPayload为HTTP的请求body的。如果body为空那么就是空字符串。上述计算结果为:e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855

  • $CanonicalRequest为上述过程计算的结果连接,上述$CanonicalRequest 为:GET/Action=ListUsers&Version=2015-11-01content-type:application/x-www-form-urlencodedhost:iam.api.ksyun.comx-amz-date:20170621T075413Zcontent-type;host;x-amz-datee3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855

2.创建待签字符串

使用规范请求和额外信息(例如算法、请求日期、凭证范围和规范请求的摘要(哈希))创建待签字符串。

待签字符串计算方式如下:

$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

  • $HashedCanonicalRequest为$CanonicalRequest进行hash(sha256)计算的结果。

3.创建签名密钥

使用 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');

4.计算签名

在派生签名密钥后,通过对待签字符串执行加密哈希操作来计算签名。使用派生的签名密钥作为此操作的哈希密钥。

计算签名的结果逻辑如下:

$Signature = hash_hmac('sha256', $StrToSign, $signKey);

5、将签名中的信息添加到请求

在计算签名后,将其添加到请求的 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示例

主要SDK:

PHP

JAVA

PYTHON

其他语言签名算法参考:

GOLANG

JS

RUBY

金山云,开启您的云计算之旅

注册有礼