Envelope encryption is an encryption mechanism similar to the digital envelope technology.
The mechanism encrypts data by using data keys that are encapsulated in an envelope.
This ensures security during the storage, transfer, and use of data keys. Customer
master keys (CMKs) are not used to directly encrypt or decrypt data. This topic describes
how to use envelope encryption to encrypt and decrypt local data.
Background information
You may encounter the following issues when you use data keys:
- Security risks: Security risks such as eavesdropping and phishing may occur during
the process of transferring your sensitive data to Alibaba Cloud services over a network.
- Absence of mutual trust and reliable credentials: You may not trust Alibaba Cloud
services and may not want to upload your sensitive data to Alibaba Cloud services.
In addition, Alibaba Cloud cannot prove that Alibaba Cloud will never misuse or disclose
the received sensitive data.
- Poor performance and high costs: A large amount of data needs to be transferred to
Alibaba Cloud services over a secure channel. After the transfer, the data needs to
be encrypted, and the encrypted data needs to be returned. This severely affects the
service performance of Alibaba Cloud services. In addition, the transfer of a large
amount of data costs high.
Envelope encryption uses a CMK to generate a data key and then uses an offline data
key to encrypt a large amount of local data. Envelope encryption does not use a CMK
to directly encrypt or decrypt data. Envelope encryption provides the following benefits:
- Protection for data keys: Data keys are encrypted and protected. Encrypted data and
encrypted data keys can be stored together.
- Provision of trust and reliable credentials: Key Management Service (KMS) implements
access control on all operations that are performed on data keys and generates logs
for tracking. KMS also records the usage of all data keys to meet your auditing and
compliance requirements.
- High performance and cost-effectiveness: KMS calls cryptographic API operations to
generate data keys and uses offline data keys to encrypt a large amount of local data.
Scenarios
You can use envelope encryption in, but not limited to, the following scenarios:
- Encrypt business data files.
- Encrypt all data stored on disks.
How data encryption and decryption work
Use KMS to create a CMK, use the CMK to generate a data key, and then use the data
key to encrypt and decrypt local files. The following figure shows the procedure of
envelope encryption.
- Envelope encryption
Procedure:
- Create a CMK in the KMS console or by calling the CreateKey operation.
- Call the GenerateDataKey operation to generate a data key. KMS returns the plaintext and ciphertext of the
data key.
- Use the plaintext data key to encrypt local files and then delete the plaintext data
key from the memory.
- Store the ciphertext data key and the encrypted files on a persistent storage device
or service.
- Envelope decryption
Procedure:
- Retrieve the ciphertext data key and the encrypted files from the persistent storage
device or service.
- Call the Decrypt operation to decrypt the ciphertext data key. The plaintext data key is returned.
- Use the plaintext data key to decrypt the encrypted files and then delete the plaintext
data key from the memory.
Related operations for encryption and decryption
You can call the KMS API operations described in the following table to encrypt and
decrypt local data.
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 returned
by the GenerateDataKey operation. You do not need to specify a CMK.
|
Use Alibaba Cloud CLI to encrypt and decrypt local files
- Call the CreateKey operation to create a CMK.
aliyun kms CreateKey
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 to use 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.
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.encode('utf-8'))
lines = [datakey_encrypted, base64.b64encode(cipher.nonce).decode('utf-8'), base64.b64encode(ciphertext).decode('utf-8'), base64.b64encode(tag).decode('utf-8')]
WriteTextFile(out_file, lines)
clt = client.AcsClient('Access-Key-Id', '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.
- ./data/sales.csv.cipher is the ciphertext file.
- ./data/decrypted_sales.csv is the returned plaintext 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 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('Access-Key-Id','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
)
Use an SDK to encrypt and decrypt local files
You can use one of the following SDKs to implement envelope encryption:
- KMS SDK
Use KMS SDK to call the GenerateDataKey operation to generate a data key. Then, use
a third-party encryption library and the data key to encrypt your data. After the
encryption process is complete, encapsulate the ciphertext data key and the encrypted
data in an envelope.
For more information about the sample code of KMS SDK, see Code samples of KMS SDK for Java.
- Encryption SDK
Encryption SDK provides the best practices of envelope encryption. You can implement
encryption and decryption with ease by using Encryption SDK.
For more information about the sample code of Encryption SDK, see Quick start of Encryption SDK for Java.