敏感数据加密实践

最近更新时间:2026-04-01 18:00:24

我的收藏
数据湖计算(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 target
USING (
SELECT c_customer_sk, aes_key_v2() AS c_key
FROM tpcds_sql_orc.customer
) AS source
ON target.c_customer_sk = source.c_customer_sk
WHEN NOT MATCHED THEN
INSERT (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_profile
SELECT
c.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 c
JOIN tpcds_sql_orc.cryptokey k
ON 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() 解密数据。
SELECT
p.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_email
FROM tpcds_sql_orc.customer_profile p
JOIN tpcds_sql_orc.cryptokey k
ON 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 格式创建。