签名机制

最近更新时间:2019-04-25 11:58:10

签名机制

账单服务的openAPI调用采用AWS签名算法版本4,具体可以参考AWS文档,支持GET方法,GET方法所有请求参数包括signature放置在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名称排序后的结果

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

      然后处理请求Body,

    6. 对请求body使用哈希算法(SHA256)计算哈希值,并将二进制哈希值结果用16进制编码表示出来(且不使用大写字符),伪代码
      HashedPayload = Lowercase(HexEncode(Hash(requestPayload)))

      此时,

    7. 将上述i-vi步骤的结果连接成一个字符串,即为正规化请求(Canonical Request)
    8. vii步的正规化请求使用vi步的哈希算法计算哈希值
  2. 创建签名字符串

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

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

    其中,签名算法(Algorithm)为AWS4-HMAC-SHA256,请求日期(RequestDate)格式YYYYMMDD'T'HHMMSS'Z' ,信任状(CredentialScope)格式为YYYYMMDD/region/service/aws4_request(包括请求日期(ISO 8601 基本格式)),正规化请求哈希值为上述1中第viii步的结果(注意结尾不附加“换行符”)

  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值(第一个为私有访问密钥字符串),而data值则依次为信任状中的各项内容(日期、region、服务、结尾字符串);HMAC算法采用HMAC-SHA256,返回值为哈希值二进制形式(256bit,32字节),不需要做8/16进制编码显示。

    2. 计算签名,伪代码如下:
      
      signature = HexEncode(HMAC(derived-

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

立即注册