阿里雲使用者在雲上部署IT資產,需要對敏感性資料進行加密保護。如果被加密的資料對象較小(小於6 KB),則可以通過Key Management Service(Key Management Service)的密碼運算API,線上對資料直接加解密。本文以加密SSL認證私密金鑰為例,介紹如何調用KMS API實現對資料的線上加密和解密。
背景資訊
典型的使用情境包括(但不限於):
對設定檔的加密
對SSL私密金鑰的加密
產品架構
使用者的資料會通過安全通道傳遞到KMS服務端,服務端完成加密和解密後,操作結果通過安全通道返回給使用者。具體架構如下圖所示。 操作流程如下:
通過KMS控制台或者調用CreateKey介面,建立一個使用者主要金鑰(CMK)。
調用KMS服務的Encrypt介面,將明文認證加密為密文認證。
將密文認證部署在雲端服務器上。
當伺服器啟動需要使用認證時,調用KMS服務的Decrypt介面將密文認證解密為明文認證。
相關API
您可以調用以下KMS API,完成對資料的加密或解密操作。
API名稱 | 說明 |
建立使用者主要金鑰(CMK)。 | |
為指定使用者主要金鑰建立一個別名。 | |
指定CMK,由KMS加密資料。 | |
解密KMS直接加密的資料,不需要指定CMK。 |
加密/解密認證密鑰
阿里雲帳號AccessKey擁有所有OpenAPI的存取權限,建議您使用RAM使用者進行API訪問或日常營運。強烈建議不要把AccessKey ID和AccessKey Secret儲存到工程代碼裡,否則可能導致AccessKey泄露,威脅您帳號下所有資源的安全。
本樣本以將AccessKey配置在環境變數ALIBABA_CLOUD_ACCESS_KEY_ID和ALIBABA_CLOUD_ACCESS_KEY_SECRET的方式來實現身分識別驗證為例。
更多認證資訊配置方式,請參見管理訪問憑據。
不同作業系統的環境變數配置方法不同,具體操作,請參見在Linux、macOS和Windows系統配置環境變數。
調用CreateKey,建立使用者主要金鑰。
aliyun kms CreateKey
預期輸出:
{ "KeyMetadata": { "CreationDate": "2019-04-08T07:45:54Z", "Description": "", "KeyId": "1234abcd-12ab-34cd-56ef-12345678****", "KeyState": "Enabled", "KeyUsage": "ENCRYPT/DECRYPT", "DeleteDate": "", "Creator": "151266687691****", "Arn": "acs:kms:cn-hangzhou:151266687691****:key/1234abcd-12ab-34cd-56ef-12345678****", "Origin": "Aliyun_KMS", "MaterialExpireTime": "" }, "RequestId": "2a37b168-9fa0-4d71-aba4-2077dd9e80df" }
可選:給主要金鑰添加別名(推薦步驟)。
別名是使用者主要金鑰的可選標識。如果使用者不建立別名,也可以直接使用密鑰的ID。
aliyun kms CreateAlias --AliasName alias/Apollo/WorkKey --KeyId 1234abcd-12ab-34cd-56ef-12345678****
說明其中,
Apollo/WorkKey
表示Apollo專案中的工作密鑰(當前被用於加密的密鑰),並在後續範例程式碼中使用此別名。即表示應用可以使用alias/Apollo/WorkKey
調用加密API。加密認證私密金鑰(業務系統對SSL私密金鑰認證進行加密保護)。
範例程式碼中:
使用者主要金鑰別名:
alias/Apollo/WorkKey
。明文認證檔案:./certs/key.pem。
輸出的密文認證檔案:./certs/key.pem.cipher。
#!/usr/bin/env python #coding=utf-8 import json from aliyunsdkcore import client from aliyunsdkkms.request.v20160120 import EncryptRequest from aliyunsdkkms.request.v20160120 import DecryptRequest def KmsEncrypt(client, plaintext, key_alias): request = EncryptRequest.EncryptRequest() request.set_accept_format('JSON') request.set_KeyId(key_alias) request.set_Plaintext(plaintext) response = json.loads(client.do_action(request)) return response.get("CiphertextBlob") def ReadTextFile(in_file): file = open(in_file, 'r') content = file.read() file.close() return content def WriteTextFile(out_file, content): file = open(out_file, 'w') file.write(content) file.close() clt = client.AcsClient(os.getenv("ALIBABA_CLOUD_ACCESS_KEY_ID"),os.getenv("ALIBABA_CLOUD_ACCESS_KEY_SECRET"),'<Region-Id>') key_alias = 'alias/Apollo/WorkKey' in_file = './certs/key.pem' out_file = './certs/key.pem.cipher' # Read private key file in text mode in_content = ReadTextFile(in_file) # Encrypt ciphertext = KmsEncrypt(clt, in_content, key_alias) # Write encrypted key file in text mode WriteTextFile(out_file, ciphertext)
解密認證私密金鑰(業務系統對部署在雲上的密文認證私密金鑰進行解密)。
範例程式碼中:
部署的密文認證檔案:./certs/key.pem.cipher。
輸出的明文認證檔案:./certs/decrypted_key.pem。
#!/usr/bin/env python #coding=utf-8 import json from aliyunsdkcore import client from aliyunsdkkms.request.v20160120 import EncryptRequest from aliyunsdkkms.request.v20160120 import DecryptRequest def KmsDecrypt(client, ciphertext): request = DecryptRequest.DecryptRequest() request.set_accept_format('JSON') request.set_CiphertextBlob(ciphertext) response = json.loads(client.do_action(request)) return response.get("Plaintext") def ReadTextFile(in_file): file = open(in_file, 'r') content = file.read() file.close() return content def WriteTextFile(out_file, content): file = open(out_file, 'w') file.write(content) file.close() clt = client.AcsClient(os.getenv("ALIBABA_CLOUD_ACCESS_KEY_ID"),os.getenv("ALIBABA_CLOUD_ACCESS_KEY_SECRET"),'<Region-Id>') in_file = './certs/key.pem.cipher' out_file = './certs/decrypted_key.pem' # Read encrypted key file in text mode in_content = ReadTextFile(in_file) # Decrypt ciphertext = KmsDecrypt(clt, in_content) # Write Decrypted key file in text mode WriteTextFile(out_file, ciphertext)