最近更新时间:2024-02-26 15:54:14
API网关的openAPI调用采用AWS签名算法版本4,具体可以参考AWS文档,支持GET和POST两种HTTP方法,GET方法所有请求参数包括signature放置在url中,POST方法则将Signature以名为authorization header的形式放置在header中,其主要区别在于GET方式处理的请求url长度不能过长。
签名计算的主要流程如下:
在签名前,首先将请求进行正规化格式化,目的是让签名计算过程无二意,其主要过程伪代码如下:
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)**<a id="1_viii"/>
8. 将vii步的正规化请求使用vi步的哈希算法计算哈希值
签名字符串主要包含请求以及正规化请求的元数据信息,由签名算法、请求日期、信任状和正规化请求哈希值连接组成,伪代码如下:
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步的结果(注意结尾不附加“换行符”)
在计算签名前,首先从私有访问密钥(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-signing-key, string-to-sign))
使用HMAC-SHA256算法,以签名密钥作为key,签名字符串作为data计算签名,签名后的二进制哈希值结果以16进制编码输出。
纯净模式