操作总览
列级加密的实施分为以下四个步骤:
·步骤一:创建数据库和表
在 DataLakeCatalog 下创建数据库,并分别建立密钥表(存储每位客户的 AES 密钥)和源数据表(包含需要加密的敏感字段)。
·步骤二:生成加密密钥
使用 aes_key_v2() 函数为每条记录生成唯一的 AES 密钥,通过 MERGE INTO 语句写入密钥表,确保已有记录不会重复生成密钥。
·步骤三:加密敏感数据
创建加密资料表,将源数据表与密钥表关联,使用 aes_encrypt_v2() 对指定敏感列进行加密后写入,非敏感列保持明文不变。
·步骤四:解密读取数据
授权用户通过关联加密资料表与密钥表,使用 aes_decrypt_v2() 将密文还原为明文,实现按需解密读取。
注意:前提条件:
核心函数
·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_key FROM tpcds_sql_orc.customer) AS sourceON target.c_customer_sk = source.c_customer_skWHEN 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_profileSELECT 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 cJOIN 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_emailFROM tpcds_sql_orc.customer_profile pJOIN 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 进行解密。返回原始明文字符串。 |
注意:说明:
实践建议
1. 密钥独立存储: 始终将加密密钥存储在专用的密钥表中,与加密数据分开存放。这样可以实现细粒度的访问控制——有权访问加密表但无权访问密钥表的用户将无法解密数据。
2. 使用 MERGE INTO 生成密钥: 使用 MERGE INTO 可以确保已有客户保留原始密钥,同时为新客户生成新密钥。这能防止密钥重复和数据损坏。
3. 保持 AAD 值一致: AAD(附加认证数据)参数在加密和解密时必须完全匹配。建议使用稳定的唯一标识符(如主键)。
4. 访问控制: 配置 DLC 权限,确保只有授权角色才能查询密钥表。普通用户应仅有权访问加密后的资料表。
5. 密钥轮换: 如需轮换密钥,请先使用 aes_key_v2() 生成新密钥,用旧密钥解密现有数据,再用新密钥重新加密,最后更新密钥表。
注意:限制说明: