Define the encrypt_udf.py class
import base64
from alibabacloud_kms20160120.models import GenerateDataKeyRequest
from alibabacloud_kms_kms20160120.models import KmsConfig, KmsRuntimeOptions
from alibabacloud_kms_kms20160120.transfer_client import TransferClient
from cryptography.hazmat.primitives.ciphers import Cipher, algorithms, modes
from odps.distcache import get_cache_file
import random
import string
import kms_udf_constant
import kms_udf_utils
class EncryptUDF(object):
def __init__(self):
cache_file = get_cache_file(kms_udf_constant.UDF_CONFIG_CACHE_FILE)
self.config_dict = kms_udf_utils.properties_to_dict(cache_file)
cache_file.close()
kms_config = KmsConfig(
protocol='https',
client_key_file=kms_udf_utils.get_config_value(self.config_dict, kms_udf_constant.KMS_CLIENT_KEY_FILE_KEY),
password=kms_udf_utils.get_config_value(self.config_dict, kms_udf_constant.KMS_CLIENT_KEY_PASSWORD_KEY),
endpoint=kms_udf_utils.get_config_value(self.config_dict, kms_udf_constant.KMS_INSTANCE_ENDPOINT_KEY),
)
self.ca_file_path = kms_udf_utils.get_config_value(self.config_dict, kms_udf_constant.KMS_INSTANCE_CA_FILE_KEY)
self.keyId = kms_udf_utils.get_config_value(self.config_dict, kms_udf_constant.UDF_ENCRYPT_KEY_ID_KEY)
self.instance_client = TransferClient(kms_config=kms_config)
resp = self.generate_data_key()
self.encrypted_data_key_part = (kms_udf_constant.ENCRYPT_DATA_KEY_FORMAT %
len(resp.body.ciphertext_blob) + resp.body.ciphertext_blob)
self.plaintext = resp.body.plaintext
self.ciphertext_blob = resp.body.ciphertext_blob
def evaluate(self, data):
if kms_udf_utils.is_null(data):
return data
iv = bytes(''.join(random.sample(string.ascii_letters + string.digits, kms_udf_constant.GCM_IV_LENGTH)),
encoding="utf-8")
data_bytes = data.encode("utf-8")
encryptor = Cipher(
algorithms.AES(base64.b64decode(self.plaintext)),
modes.GCM(iv),
).encryptor()
ciphertext = encryptor.update(data_bytes) + encryptor.finalize()
return self.encrypted_data_key_part + str(base64.b64encode(iv), "utf-8") + str(
base64.b64encode(ciphertext + encryptor.tag), "utf-8")
def generate_data_key(self):
request = GenerateDataKeyRequest()
request.key_id = self.keyId
request.number_of_bytes = kms_udf_constant.DEFAULT_NUMBER_OF_BYTES
runtime = KmsRuntimeOptions(
ca=self.ca_file_path
)
return self.instance_client.generate_data_key_with_options(request, runtime)
Note
The following API operations of KMS are used.
For more information about API operations of KMS and how to call the API operations, see API references and SDK references.