阿里云用户在云上部署IT资产,需要对敏感数据进行加密保护。如果被加密的数据对象较小(小于6 KB),则可以通过密钥管理服务KMS(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)