数据湖计算(DLC)的列级加密功能允许您在列级别对敏感数据进行加密,例如邮箱地址、手机号码或身份证号等。通过在独立的密钥表中管理加密密钥,并利用 DLC 内置的 AES 加密函数,您可以在保护敏感字段的同时,让其他列以明文形式保留以满足正常业务查询需求。
操作总览
列级加密的实施分为以下四个步骤:
步骤一:创建数据库和表
在 DataLakeCatalog 下创建数据库,并分别建立密钥表(存储每位客户的 AES 密钥)和源数据表(包含需要加密的敏感字段)。
步骤二:生成加密密钥
使用 aes_key_v2() 函数为每条记录生成唯一的 AES 密钥,通过 MERGE INTO 语句写入密钥表,确保已有记录不会重复生成密钥。
步骤三:加密敏感数据
创建加密资料表,将源数据表与密钥表关联,使用 aes_encrypt_v2() 对指定敏感列进行加密后写入,非敏感列保持明文不变。
步骤四:解密读取数据
授权用户通过关联加密资料表与密钥表,使用 aes_decrypt_v2() 将密文还原为明文,实现按需解密读取。
前提条件:
使用 DLC 标准 Spark 引擎。
具有创建表和执行查询的相应权限。
核心函数
aes_key_v2():为每条记录生成唯一的 AES 加密密钥。
aes_encrypt_v2(key, data, id):使用 AES 密钥和标识符对明文字符串进行加密。
aes_decrypt_v2(key, data, id):将加密字符串解密还原为明文。
假设您要对 tpcds_sql_orc 数据库下的 customer 表信息进行函数加密,操作步骤如下:
步骤一:创建数据库和表
1.1 创建数据库
打开数据探索页面,选择您的标准 Spark 引擎,运行以下 SQL 创建数据库:
CREATE DATABASE IF NOT EXISTS tpcds_sql_orc;
1.2 创建密钥表
创建一张用于存储每条记录加密密钥的表。每一行将客户标识符映射到其唯一的 AES 密钥。
CREATE TABLE IF NOT EXISTS tpcds_sql_orc.cryptokey (c_customer_sk INT,c_key STRING) USING iceberg;
1.3 创建源数据表
创建一张包含敏感字段(如邮箱地址)的原始数据表:
CREATE TABLE IF NOT EXISTS tpcds_sql_orc.customer (c_customer_sk INT,c_first_name STRING,c_last_name STRING,c_email_address STRING) USING iceberg;
插入示例数据:
INSERT INTO tpcds_sql_orc.customer VALUES(1, 'John', 'Doe', 'john.doe@example.com'),(2, 'Jane', 'Smith', 'jane.smith@example.com'),(3, 'Bob', 'Wilson', 'bob.wilson@example.com');
步骤二:生成加密密钥
使用 MERGE INTO 配合 aes_key_v2() 为每个客户生成唯一的 AES 密钥,并将其插入密钥表。MERGE INTO 语句确保仅为新客户(即密钥表中尚不存在的客户)生成新密钥。
MERGE INTO tpcds_sql_orc.cryptokey AS targetUSING (SELECT c_customer_sk, aes_key_v2() AS c_keyFROM tpcds_sql_orc.customer) AS sourceON target.c_customer_sk = source.c_customer_skWHEN NOT MATCHED THENINSERT (c_customer_sk, c_key)VALUES (source.c_customer_sk, source.c_key);
验证生成的密钥:
SELECT * FROM tpcds_sql_orc.cryptokey;
预期结果:
c_customer_sk | c_key |
1 | Ev3LK4ZN7ya06WQKZMVSm7N4GeOd2Rq4omucnuECHs= |
2 | inBr4BTgPWoAaCjNaGWpZsUaV0RAbFwjRxhOganF4= |
3 | xSpCNYO+qbj/hFWzUKcZd4fP/bMOauKO7zunxdcY= |
说明:
每个密钥是一个 Base64 编码的 AES 密钥,每个客户唯一。
步骤三:加密敏感数据
创建一张新表用于存储加密后的用户资料数据,然后通过关联源数据表和密钥表,对邮箱地址进行加密写入。
3.1 创建加密资料表
CREATE TABLE IF NOT EXISTS tpcds_sql_orc.customer_profile (c_customer_sk INT,c_first_name STRING,c_last_name STRING,c_email_address STRING) USING iceberg;
3.2 写入加密数据
使用 aes_encrypt_v2(key, data, id) 对 c_email_address 列进行加密。第三个参数(id)作为 AAD(附加认证数据),用于将密文与特定记录绑定。
INSERT INTO tpcds_sql_orc.customer_profileSELECTc.c_customer_sk,c.c_first_name,c.c_last_name,aes_encrypt_v2(k.c_key, c.c_email_address, CAST(c.c_customer_sk AS STRING))FROM tpcds_sql_orc.customer cJOIN tpcds_sql_orc.cryptokey kON c.c_customer_sk = k.c_customer_sk;
验证加密后的数据:
SELECT * FROM tpcds_sql_orc.customer_profile;
预期结果:
c_customer_sk | c_first_name | c_last_name | c_email_address |
1 | John | Doe | E5v9kORhAZceEe251xrUQbfx+PNkP4Q2Z2... |
2 | Jane | Smith | Y3aalCHBAMYzFDxqUgDQd8S3EXRS8Wby250p... |
3 | Bob | Wilson | KMEV9CUkdXd7YFwwcdqMC2phd2KHPrPRGBXU... |
可以看到 c_email_address 列已变为加密密文,而 c_first_name 和 c_last_name 仍保持明文。
步骤四:解密读取数据
授权用户可以通过关联加密表和密钥表,使用 aes_decrypt_v2() 解密数据。
SELECTp.c_customer_sk,p.c_first_name,p.c_last_name,aes_decrypt_v2(k.c_key, p.c_email_address, CAST(p.c_customer_sk AS STRING)) AS decrypted_emailFROM tpcds_sql_orc.customer_profile pJOIN tpcds_sql_orc.cryptokey kON p.c_customer_sk = k.c_customer_sk;
预期结果:
c_customer_sk | c_first_name | c_last_name | decrypted_email |
1 | John | Doe | john.doe@example.com |
2 | Jane | Smith | jane.smith@example.com |
3 | Bob | Wilson | bob.wilson@example.com |
原始明文邮箱地址已成功还原。
函数参考
函数 | 语法 | 说明 |
aes_key_v2() | aes_key_v2() | 生成一个随机 AES 加密密钥(返回 Base64 编码字符串)。 |
aes_encrypt_v2 | aes_encrypt_v2(key, plaintext, aad) | 使用给定的 key 和 aad(附加认证数据)对 plaintext 进行加密。返回 Base64 编码的密文字符串。 |
aes_decrypt_v2 | aes_decrypt_v2(key, ciphertext, aad) | 使用给定的 key 和 aad 对 ciphertext 进行解密。返回原始明文字符串。 |
说明:
key(STRING):AES 加密密钥,由 aes_key_v2() 生成。
plaintext(STRING):待加密的明文数据。
ciphertext(STRING):待解密的加密数据。
aad(STRING):附加认证数据(Additional Authenticated Data)。加密和解密时该值必须一致。通常使用唯一的记录标识符(如 CAST(c_customer_sk AS STRING))。
实践建议
1. 密钥独立存储: 始终将加密密钥存储在专用的密钥表中,与加密数据分开存放。这样可以实现细粒度的访问控制——有权访问加密表但无权访问密钥表的用户将无法解密数据。
2. 使用 MERGE INTO 生成密钥: 使用 MERGE INTO 可以确保已有客户保留原始密钥,同时为新客户生成新密钥。这能防止密钥重复和数据损坏。
3. 保持 AAD 值一致: AAD(附加认证数据)参数在加密和解密时必须完全匹配。建议使用稳定的唯一标识符(如主键)。
4. 访问控制: 配置 DLC 权限,确保只有授权角色才能查询密钥表。普通用户应仅有权访问加密后的资料表。
5. 密钥轮换: 如需轮换密钥,请先使用 aes_key_v2() 生成新密钥,用旧密钥解密现有数据,再用新密钥重新加密,最后更新密钥表。
限制说明:
列级加密函数(aes_key_v2、aes_encrypt_v2、aes_decrypt_v2)仅在标准 Spark 引擎中可用。
加密列的数据类型必须为 STRING。
在 DataLakeCatalog 中,表必须使用 Iceberg 格式创建。