为保证API的安全调用,KMS会对每个API请求通过签名(Signature)进行身份验证。

安全验证

安全验证基于KMS实例的应用接入点Client Key,使用非对称签名算法完成,以便实现以下需求:

  • 确认发起API请求的用户身份。

    因为在发送请求前需要用户指定生成数字签名的应用接入点Client Key,在服务端即可通过该应用接入点Client Key确认用户身份,以便管理访问权限。

  • 确认API请求在网络传输过程中是否被篡改。

    因为服务端会对收到的请求内容进行数字签名验证,若请求内容在网络上被篡改,则无法通过数字签名验证。

安全验证流程如下:

  1. 请求端根据API请求内容(包括HTTP Header和Body)生成签名字符串。
  2. 请求端使用应用接入点Client Key的私钥(PrivateKeyData),对步骤1生成的签名字符串进行签名,形成该API请求的数字签名。
  3. 请求端将API请求内容和数字签名一同发送给服务端。
  4. 服务端在接收到请求后使用Client Key的公钥验证数字签名。如果验证通过则认为该请求通过安全验证,否则直接拒绝该请求。
    说明 服务端会在后台取得该请求使用的应用接入点Client Key的公钥。

签名过程

为了通过API请求的安全验证,用户需要在客户端对API请求进行签名(即生成正确的数字签名),并使用HTTP Authorization头在网络上传输该请求的数字签名。Authorization头示例如下:
Authorization = "TOKEN" + " " + Signature

其中,Signature是使用应用接入点Client Key的私钥(PrivateKeyData)对API请求进行签名的值。您可以根据以下步骤构造Signature。

  1. 准备KMS实例的应用接入点Client Key。
    为API请求生成签名,需使用应用接入点Client Key的私钥。您可以使用已经存在的Client Key,也可以创建新的Client Key,但需要保证使用的Client Key为启用状态。
  2. 生成请求的签名字符串。
    KMS API的签名字符串由HTTP请求中的Method、Header和Body信息一同生成,具体如下:
    SignString = HTTP-METHOD + "\n"
                 + CONTENT-SHA256 + "\n"
                 + CONTENT-TYPE + "\n"
                 + DATE + "\n"
                 + CanonicalizedKMSHeaders + "\n"
                 + CanonicalizedResource
    其中,\n表示换行转义字符,+表示字符串连接操作,其余部分定义如下:
    名称说明示例
    HTTP-METHODHTTP请求的方法名称。PUT、GET、POST等。
    CONTENT-SHA256HTTP请求头的Content-SHA256值。AE71057543002AD513AB88D78509A1214192C09F20302C4BF8F59B7EB565****
    CONTENT-TYPEHTTP请求中Body部分的类型。application/x-protobuf
    DATEHTTP请求中的标准时间戳头(遵循RFC 1123格式,使用GMT标准时间)。Mon, 27 Sep 2021 11:47:26 GMT
    CanonicalizedKMSHeaders由HTTP请求中KMS自定义头构造(以x-kms为前缀)的字符串。x-kms-acccesskeyid:KAAP.9c84ad54-d3c5-47c3-b0e7-7c26d509****\nx-kms-apiname:Encrypt\nx-kms-apiversion:dkms-gcs-0.2\nx-kms-signaturemethod:RSA_PKCS1_SHA_256
    CanonicalizedResource固定为//
    对于部分无Body的HTTP请求,CONTENT-SHA256CONTENT-TYPE两个字段为空字符串,此时签名字符串的生成方式如下:
    SignString = HTTP-METHOD + "\n"
                 + "\n"
                 + "\n"
                 + DATE + "\n"
                 + CanonicalizedKMSHeaders + "\n"
                 + CanonicalizedResource
    KMS API中引入了一个自定义请求头x-kms。如果您在请求中指定了该请求头,则其值会加入签名计算。CanonicalizedKMSHeaders的生成方式如下:
    1. 将所有以x-kms为前缀的HTTP请求头的名称转换成小写字母。
    2. 将所有自定义请求头按照字典顺序进行升序排序。
    3. 删除请求头和内容之间分隔符两端出现的任何空格。例如: CONTENT-TYPE : application/x-protobuf 转化为CONTENT-TYPE:application/x-protobuf
    4. 将所有的头和内容用\n分隔符组合成最后的CanonicalizedKMSHeaders。
  3. 生成请求的数字签名。
    API当前只支持一种数字签名算法(RSA_PKCS1_SHA_256),签名公式如下:
    Signature=Base64(RSA_PKCS1_SHA_256(SignString, AAP_KEY))

    生成数字签名时,请关注以下内容:

    • 将签名算法生成的值使用标准Base64进行编码。
    • 使用RFC 3447中定义的RSASSA-PKCS1-v1_5方法进行签名。
    • 在计算出数字签名后,使用签名值构建完整的API请求安全验证头(Authorization)。
    • 参与签名计算的字符串必须为UTF-8编码。含有汉字的签名字符串必须先进行UTF-8编码,再计算最终签名。
    • CONTENT-SHA256CONTENT-TYPE在请求中不是必需的,如果CONTENT-SHA256CONTENT-TYPE为空时以换行符\n代替。

签名示例

为了帮助您更好地理解整个请求签名的流程,我们以Encrypt为例来演示签名过程。

假设KMS API签名的应用接入点Client Key和Encrypt接口的加密参数如下:
  • 应用接入点Client Key
    {
      "KeyId": "KAAP.9c84ad54-d3c5-47c3-b0e7-7c26d509****",
      "PrivateKeyData": "MIIJqwIB****UcQ=="
    }
  • Encrypt接口的加密参数
    keyId = "1234abcd-12ab-34cd-56ef-12345678****"
    plaintext = "plain text"

签名过程示例如下:

  1. 按照KMS API定义构建如下HTTP请求。
    POST / HTTP/1.1
    Date: Mon, 27 Sep 2021 11:47:26 GMT
    Host: kst-xxxx.cryptoservice.kms.aliyuncs.com
    Accept: application/x-protobuf
    Content-SHA256: AE71057543002AD513AB88D78509A1214192C09F20302C4BF8F59B7EB565****
    Content-Length: 40
    Content-Type: application/x-protobuf
    x-kms-acccesskeyid: KAAP.9c84ad54-d3c5-47c3-b0e7-7c26d509****
    x-kms-apiversion: dkms-gcs-0.2
    x-kms-apiname: Encrypt
    x-kms-signaturemethod: RSA_PKCS1_SHA_256
    
    <加密参数序列化成ProtoBuffer格式的字节流>

    其中,加密参数被序列化成ProtoBuffer格式后作为请求Body。该请求的Content-Type头的值指定为application/x-protobufContent-SHA256头的值是请求Body经过SHA-256计算后的Hex编码大写字符串。

  2. 构造待签名字符串。
    POST\nAE71057543002AD513AB88D78509A1214192C09F20302C4BF8F59B7EB56551E2\napplication/x-protobuf\nMon, 27 Sep 2021 11:47:26 GMT\nx-kms-acccesskeyid:KAAP.9c84ad54-xxxx-xxxx-xxxx-7c26d509a55d\nx-kms-apiname:Encrypt\nx-kms-apiversion:dkms-gcs-0.2\nx-kms-signaturemethod:RSA_PKCS1_SHA_256\n/
  3. 使用已有Client Key中私钥(PrivateKeyData)进行签名运算,得到签名值并进行Base64编码。
    BPwBSB9NkxxuepqJ2zRtLT8jgv0FIAELJI2U79k8OPO7M7Y18Sz6+njTSwYWeIIQpJIJKx+mGBl/aR9opPbfQ+PhH+78rIPLJYNAJRvvaSUW/cRr4BMc1ByRXvuBmIcI81MQGutuU8uLnQYh9AURdklpqcW3ODz5OfsbuuxTGV17COoSO10tW3ltADumaMczFGTM0qCYi/pyh8p8i/gpwC3EXo540n5mqEmLexYIWb5/Fo+VonqZxZ3UuhZPw3vQ8uvqMGqvvw0xxKsblGuEdNSHcy/GYGRTFYugwOojZxd7TpADTqys+7SYaBWT38HnQLcH04DeD5rKkhRK7au8HQ==
  4. 发送包含签名的HTTP请求内容。
    POST / HTTP/1.1
    Date: Mon, 27 Sep 2021 11:47:26 GMT
    Host: kst-xxxx.cryptoservice.kms.aliyuncs.com
    Accept: application/x-protobuf
    Content-SHA256: AE71057543002AD513AB88D78509A1214192C09F20302C4BF8F59B7EB565****
    Content-Length: 40
    Content-Type: application/x-protobuf
    x-kms-acccesskeyid: KAAP.9c84ad54-d3c5-47c3-b0e7-7c26d509****
    x-kms-apiversion: dkms-gcs-0.2
    x-kms-apiname: Encrypt
    x-kms-signaturemethod: RSA_PKCS1_SHA_256
    Authorization: TOKEN BPwBSB9NkxxuepqJ2zRtLT8jgv0FIAELJI2U79k8OPO7M7Y18Sz6+njTSwYWeIIQpJIJKx+mGBl/aR9opPbfQ+PhH+78rIPLJYNAJRvvaSUW/cRr4BMc1ByRXvuBmIcI81MQGutuU8uLnQYh9AURdklpqcW3ODz5OfsbuuxTGV17COoSO10tW3ltADumaMczFGTM0qCYi/pyh8p8i/gpwC3EXo540n5mqEmLexYIWb5/Fo+VonqZxZ3UuhZPw3vQ8uvqMGqvvw0xxKsblGuEdNSHcy/GYGRTFYugwOojZxd7TpADTqys+7SYaBWT38HnQLcH04DeD5rKkhRK7au8HQ==
    
    <加密参数序列化成ProtoBuffer格式的字节流>