為保證API的安全調(diào)用,KMS會對每個API請求通過簽名(Signature)進(jìn)行身份驗(yàn)證。
安全驗(yàn)證
安全驗(yàn)證基于KMS實(shí)例的應(yīng)用接入點(diǎn)Client Key,使用非對稱簽名算法完成,以便實(shí)現(xiàn)以下需求:
- 確認(rèn)發(fā)起API請求的用戶身份。
因?yàn)樵诎l(fā)送請求前需要用戶指定生成數(shù)字簽名的應(yīng)用接入點(diǎn)Client Key,在服務(wù)端即可通過該應(yīng)用接入點(diǎn)Client Key確認(rèn)用戶身份,以便管理訪問權(quán)限。
- 確認(rèn)API請求在網(wǎng)絡(luò)傳輸過程中是否被篡改。
因?yàn)榉?wù)端會對收到的請求內(nèi)容進(jìn)行數(shù)字簽名驗(yàn)證,若請求內(nèi)容在網(wǎng)絡(luò)上被篡改,則無法通過數(shù)字簽名驗(yàn)證。
安全驗(yàn)證流程如下:
- 請求端根據(jù)API請求內(nèi)容(包括HTTP Header和Body)生成簽名字符串。
- 請求端使用應(yīng)用接入點(diǎn)Client Key的私鑰(PrivateKeyData),對步驟1生成的簽名字符串進(jìn)行簽名,形成該API請求的數(shù)字簽名。
- 請求端將API請求內(nèi)容和數(shù)字簽名一同發(fā)送給服務(wù)端。
- 服務(wù)端在接收到請求后使用Client Key的公鑰驗(yàn)證數(shù)字簽名。如果驗(yàn)證通過則認(rèn)為該請求通過安全驗(yàn)證,否則直接拒絕該請求。說明 服務(wù)端會在后臺取得該請求使用的應(yīng)用接入點(diǎn)Client Key的公鑰。
簽名過程
為了通過API請求的安全驗(yàn)證,用戶需要在客戶端對API請求進(jìn)行簽名(即生成正確的數(shù)字簽名),并使用HTTP Authorization頭在網(wǎng)絡(luò)上傳輸該請求的數(shù)字簽名。Authorization頭示例如下:
Authorization = "TOKEN" + " " + Signature
其中,Signature是使用應(yīng)用接入點(diǎn)Client Key的私鑰(PrivateKeyData)對API請求進(jìn)行簽名的值。您可以根據(jù)以下步驟構(gòu)造Signature。
- 準(zhǔn)備KMS實(shí)例的應(yīng)用接入點(diǎn)Client Key。為API請求生成簽名,需使用應(yīng)用接入點(diǎn)Client Key的私鑰。您可以使用已經(jīng)存在的Client Key,也可以創(chuàng)建新的Client Key,但需要保證使用的Client Key為啟用狀態(tài)。
- 生成請求的簽名字符串。KMS API的簽名字符串由HTTP請求中的Method、Header和Body信息一同生成,具體如下:
SignString = HTTP-METHOD + "\n" + CONTENT-SHA256 + "\n" + CONTENT-TYPE + "\n" + DATE + "\n" + CanonicalizedKMSHeaders + "\n" + CanonicalizedResource
其中,\n
表示換行轉(zhuǎn)義字符,+
表示字符串連接操作,其余部分定義如下:名稱 說明 示例 HTTP-METHOD
HTTP請求的方法名稱。 PUT、GET、POST等。 CONTENT-SHA256
HTTP請求頭的Content-SHA256值。 AE71057543002AD513AB88D78509A1214192C09F20302C4BF8F59B7EB565**** CONTENT-TYPE
HTTP請求中Body部分的類型。 application/x-protobuf DATE
HTTP請求中的標(biāo)準(zhǔn)時間戳頭(遵循RFC 1123格式,使用GMT標(biāo)準(zhǔn)時間)。 Mon, 27 Sep 2021 11:47:26 GMT CanonicalizedKMSHeaders
由HTTP請求中KMS自定義頭構(gòu)造(以 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-SHA256
和CONTENT-TYPE
兩個字段為空字符串,此時簽名字符串的生成方式如下:SignString = HTTP-METHOD + "\n" + "\n" + "\n" + DATE + "\n" + CanonicalizedKMSHeaders + "\n" + CanonicalizedResource
KMS API中引入了一個自定義請求頭x-kms
。如果您在請求中指定了該請求頭,則其值會加入簽名計(jì)算。CanonicalizedKMSHeaders
的生成方式如下:- 將所有以
x-kms
為前綴的HTTP請求頭的名稱轉(zhuǎn)換成小寫字母。 - 將所有自定義請求頭按照字典順序進(jìn)行升序排序。
- 刪除請求頭和內(nèi)容之間分隔符兩端出現(xiàn)的任何空格。例如:
CONTENT-TYPE : application/x-protobuf
轉(zhuǎn)化為CONTENT-TYPE:application/x-protobuf
- 將所有的頭和內(nèi)容用
\n
分隔符組合成最后的CanonicalizedKMSHeaders。
- 將所有以
- 生成請求的數(shù)字簽名。API當(dāng)前只支持一種數(shù)字簽名算法(
RSA_PKCS1_SHA_256
),簽名公式如下:Signature=Base64(RSA_PKCS1_SHA_256(SignString, AAP_KEY))
生成數(shù)字簽名時,請關(guān)注以下內(nèi)容:
- 將簽名算法生成的值使用標(biāo)準(zhǔn)Base64進(jìn)行編碼。
- 使用RFC 3447中定義的RSASSA-PKCS1-v1_5方法進(jìn)行簽名。
- 在計(jì)算出數(shù)字簽名后,使用簽名值構(gòu)建完整的API請求安全驗(yàn)證頭(Authorization)。
- 參與簽名計(jì)算的字符串必須為
UTF-8
編碼。含有漢字的簽名字符串必須先進(jìn)行UTF-8
編碼,再計(jì)算最終簽名。 CONTENT-SHA256
和CONTENT-TYPE
在請求中不是必需的,如果CONTENT-SHA256
和CONTENT-TYPE
為空時以換行符\n
代替。
簽名示例
為了幫助您更好地理解整個請求簽名的流程,我們以Encrypt為例來演示簽名過程。
假設(shè)KMS API簽名的應(yīng)用接入點(diǎn)Client Key和Encrypt接口的加密參數(shù)如下:
- 應(yīng)用接入點(diǎn)Client Key
{ "KeyId": "KAAP.9c84ad54-d3c5-47c3-b0e7-7c26d509****", "PrivateKeyData": "MIIJqwIB****UcQ==" }
- Encrypt接口的加密參數(shù)
keyId = "1234abcd-12ab-34cd-56ef-12345678****" plaintext = "plain text"
簽名過程示例如下:
- 按照KMS API定義構(gòu)建如下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 <加密參數(shù)序列化成ProtoBuffer格式的字節(jié)流>
其中,加密參數(shù)被序列化成ProtoBuffer格式后作為請求Body。該請求的
Content-Type
頭的值指定為application/x-protobuf
、Content-SHA256
頭的值是請求Body經(jīng)過SHA-256計(jì)算后的Hex編碼大寫字符串。 - 構(gòu)造待簽名字符串。
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/
- 使用已有Client Key中私鑰(PrivateKeyData)進(jìn)行簽名運(yùn)算,得到簽名值并進(jìn)行Base64編碼。
BPwBSB9NkxxuepqJ2zRtLT8jgv0FIAELJI2U79k8OPO7M7Y18Sz6+njTSwYWeIIQpJIJKx+mGBl/aR9opPbfQ+PhH+78rIPLJYNAJRvvaSUW/cRr4BMc1ByRXvuBmIcI81MQGutuU8uLnQYh9AURdklpqcW3ODz5OfsbuuxTGV17COoSO10tW3ltADumaMczFGTM0qCYi/pyh8p8i/gpwC3EXo540n5mqEmLexYIWb5/Fo+VonqZxZ3UuhZPw3vQ8uvqMGqvvw0xxKsblGuEdNSHcy/GYGRTFYugwOojZxd7TpADTqys+7SYaBWT38HnQLcH04DeD5rKkhRK7au8HQ==
- 發(fā)送包含簽名的HTTP請求內(nèi)容。
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== <加密參數(shù)序列化成ProtoBuffer格式的字節(jié)流>