You must encrypt sensitive information in your IT assets that are deployed on Alibaba Cloud. If you need to encrypt a large amount of local data, you can call cryptographic API operations of Key Management Service (KMS) to generate a data key online and then use the data key to encrypt the local data offline. This encryption mechanism is known as envelope encryption.
Background information
You can use envelope encryption in, but not limited to, the following scenarios:
This topic describes how to use envelope encryption to encrypt and decrypt local files.
How data encryption and decryption work
Use KMS to create a customer master key (CMK), use the CMK to generate a data key, and then use the data key to encrypt and decrypt local files. Envelope encryption is suitable for encrypting and decrypting a large amount of data. The following figure shows the procedure of envelope encryption.
Encryption and decryption API operations
You can call the API operations described in the following table to encrypt and decrypt local data.
API operation | Description |
CreateKey | Creates a CMK. |
CreateAlias | Creates an alias for a CMK. |
GenerateDataKey | Generates a data key and uses the specified CMK to encrypt the data key. KMS returns the plaintext and ciphertext of the data key. |
Decrypt | Decrypts data that is encrypted in KMS, including the ciphertext data key generated by calling the GenerateDataKey operation. You do not need to specify a CMK. |
Encrypt and decrypt local files
Note
The AccessKey pair of an Alibaba Cloud account has permissions on all API operations. Using the AccessKey pair to perform operations is a high-risk operation. We recommend that you use a RAM user to call API operations or perform routine O&M. We recommend that you do not save the AccessKey ID and AccessKey Secret in your project code. Otherwise, the AccessKey pair may be leaked and the security of all the resources that belong to your account may be compromised.
In this example, the AccessKey pair is saved in ALIBABA_CLOUD_ACCESS_KEY_ID and ALIBABA_CLOUD_ACCESS_KEY_SECRET environment variables to implement identity authentication. For more information about how to configure authentication information, see Instantiate a client and configure a credential.
You can create a CMK and encrypt and decrypt local files by using Alibaba Cloud CLI.
Call the CreateKey operation to create a CMK.
Expected output:
{
"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"
}
Optional. Create an alias for the CMK.
Aliases are optionally used to identify CMKs. If a CMK does not have an alias, you can use the ID of the CMK to identify the CMK.
aliyun kms CreateAlias --AliasName alias/Apollo/WorkKey --KeyId 1234abcd-12ab-34cd-56ef-12345678****
Note
In this example, Apollo/WorkKey
is the alias of the CMK in the Apollo
project. You can use the alias alias/Apollo/WorkKey
in subsequent sample code to call the Encrypt operation.
Encrypt a local file.
In the following sample code:
alias/Apollo/WorkKey
is the alias of the CMK.
./data/sales.csv is the plaintext file.
./data/sales.csv.cipher is the returned ciphertext file.
#!/usr/bin/env python
#coding=utf-8
import json
import base64
from Crypto.Cipher import AES
from aliyunsdkcore import client
from aliyunsdkkms.request.v20160120 import GenerateDataKeyRequest
def KmsGenerateDataKey(client, key_alias):
request = GenerateDataKeyRequest.GenerateDataKeyRequest()
request.set_accept_format('JSON')
request.set_KeyId(key_alias)
request.set_NumberOfBytes(32)
response = json.loads(client.do_action(request))
datakey_encrypted = response["CiphertextBlob"]
datakey_plaintext = response["Plaintext"]
return (datakey_plaintext, datakey_encrypted)
def ReadTextFile(in_file):
file = open(in_file, 'r')
content = file.read()
file.close()
return content
def WriteTextFile(out_file, lines):
file = open(out_file, 'w')
for ln in lines:
file.write(ln)
file.write('\n')
file.close()
# Out file format (text)
# Line 1: b64 encoded data key
# Line 2: b64 encoded IV
# Line 3: b64 encoded ciphertext
# Line 4: b64 encoded authentication tag
def LocalEncrypt(datakey_plaintext, datakey_encrypted, in_file, out_file):
data_key_binary = base64.b64decode(datakey_plaintext)
cipher = AES.new(data_key_binary, AES.MODE_EAX)
in_content = ReadTextFile(in_file)
ciphertext, tag = cipher.encrypt_and_digest(in_content)
lines = [datakey_encrypted, base64.b64encode(cipher.nonce), base64.b64encode(ciphertext), base64.b64encode(tag)];
WriteTextFile(out_file, lines)
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 = './data/sales.csv'
out_file = './data/sales.csv.cipher'
# Generate Data Key
datakey = KmsGenerateDataKey(clt, key_alias)
# Locally Encrypt the sales record
LocalEncrypt(datakey[0], datakey[1], in_file, out_file)
Decrypt a local file.
In the following sample code:
#!/usr/bin/env python
#coding=utf-8
import json
import base64
from Crypto.Cipher import AES
from aliyunsdkcore import client
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')
lines = []
for ln in file:
lines.append(ln)
file.close()
return lines
def WriteTextFile(out_file, content):
file = open(out_file, 'w')
file.write(content)
file.close()
def LocalDecrypt(datakey, iv, ciphertext, tag, out_file):
cipher = AES.new(datakey, AES.MODE_EAX, iv)
data = cipher.decrypt_and_verify(ciphertext, tag).decode('utf-8')
WriteTextFile(out_file, data)
clt = client.AcsClient(os.getenv("ALIBABA_CLOUD_ACCESS_KEY_ID"),os.getenv("ALIBABA_CLOUD_ACCESS_KEY_SECRET"),'Region-Id')
in_file = './data/sales.csv.cipher'
out_file = './data/decrypted_sales.csv'
# Read encrypted file
in_lines = ReadTextFile(in_file)
# Decrypt data key
datakey = KmsDecrypt(clt, in_lines[0])
# Locally decrypt the sales record
LocalDecrypt(
base64.b64decode(datakey),
base64.b64decode(in_lines[1]), # IV
base64.b64decode(in_lines[2]), # Ciphertext
base64.b64decode(in_lines[3]), # Authentication tag
out_file
)