跳转至

Parquet 模块化加密

Parquet 文件中的敏感信息可以通过模块化加密机制进行保护,该机制能够对文件数据和元数据进行加密和认证,同时仍然支持常规的 Parquet 功能(列投影、谓词下推、编码和压缩)。

1 问题陈述

现有的数据保护方案(例如文件的整体加密、存储加密或加密存储客户端)可以应用于 Parquet 文件,但存在各种安全性或性能问题。在 Parquet 格式中集成加密机制可以在数据安全性、处理速度和加密粒度之间实现最佳平衡。

2 目标

  1. 通过加密保护 Parquet 数据和元数据,同时支持选择性读取(列投影、谓词下推)。
  2. 实现“客户端”加密/解密(存储客户端)。存储服务器不得看到明文数据、元数据或加密密钥。
  3. 利用认证加密,允许客户端验证检索到的数据的完整性,确保文件(或文件的部分内容)未被篡改或替换为错误版本。
  4. 允许不同的列和文件尾(footer)使用不同的加密密钥。
  5. 支持部分加密,仅加密包含敏感数据的列。
  6. 兼容 Parquet 支持的所有压缩和编码机制。
  7. 支持多种加密算法,以满足不同的安全性和性能需求。
  8. 支持两种元数据保护模式:
  9. 完整保护文件元数据。
  10. 部分保护文件元数据,以允许旧版读取器访问加密文件中的未加密列。
  11. 最小化加密的开销,包括加密文件的大小以及读写操作的吞吐量。

3 技术方案

Parquet 文件由多个独立序列化的组件组成:页面(pages)、页面头(page headers)、列索引(column indexes)、偏移索引(offset indexes)、布隆过滤器(bloom filter)头和位集(bitsets)、文件尾(footer)。Parquet 加密机制将这些组件称为“模块”(modules),并分别对每个模块进行加密,使得可以获取并解密文件尾、找到所需页面的偏移量、提取页面并解密数据。

文件加密方式灵活——每个列和文件尾可以使用相同的密钥加密,也可以使用不同的密钥加密,甚至可以选择不加密。

加密的压缩列页面在写入输出流之前进行加密。对于加密的列块,Parquet 增加了一种新的 Thrift 结构 ColumnCryptoMetaData,用于存储列加密密钥的信息。

文件尾可以选择加密或保持明文。在加密文件尾模式下,Parquet 添加了 FileCryptoMetaData 结构,其中包含文件加密算法和文件尾加密密钥的信息。在明文文件尾模式下,文件尾结构的内容可见,并通过签名来验证完整性。新增加的文件尾字段存储了文件加密算法和文件尾签名密钥的信息。

对于加密的列,以下模块始终使用相同的列密钥进行加密: - 页面及其头部(字典页和数据页) - 列索引 - 偏移索引 - 布隆过滤器头和位集

如果列密钥与文件尾密钥不同,则列元数据会被单独序列化并使用列密钥加密,在这种情况下,列元数据本身也被视为一个模块。

4 加密算法与密钥

Parquet 加密算法基于标准的 AES 对称加密。AES 在 Intel 及其他 CPU 上支持硬件加速(“AES-NI”),可被 Java(自动通过 HotSpot)或 C++(通过 OpenSSL 的 EVP-* 函数)利用。Parquet 支持所有标准的 AES 密钥长度:128、192 和 256 位。

目前实现了两种加密算法,一种基于 AES 的 GCM 模式,另一种基于 GCM 和 CTR 模式的组合。

4.1 Parquet 使用的 AES 模式

4.1.1 AES GCM

AES GCM 是一种认证加密方式,除了提供数据机密性(加密),还支持两种完整性验证级别: - 仅验证数据的完整性(默认)。 - 结合可选的 AAD(附加认证数据)验证数据完整性。

4.1.2 AES CTR

AES CTR 是一种普通的加密模式,不提供数据认证功能。它比 GCM 更快,因为它不进行完整性验证,也不会计算认证标签(authentication tag)。CTR 模式适用于不依赖完整性验证的应用场景,例如在不支持 AES 硬件加速的 Java 版本(Java 9 之前)上运行的应用。

4.2 Parquet 加密算法

4.2.1 AES_GCM_V1

该算法使用 GCM 模式加密所有模块,不使用填充(padding)。

4.2.2 AES_GCM_CTR_V1

该算法使用 GCM 模式加密除数据页面外的所有模块,数据页面使用 CTR 模式加密。

4.3 密钥元数据

Parquet 允许开发者通过 key_metadata 字节数组提供自定义的密钥管理方案,例如: - 直接存储数据密钥的字符串 ID,以便从 KMS(密钥管理服务)检索数据密钥。 - 存储加密的数据密钥和主密钥的 ID。 - 仅存储数据密钥的短 ID,并将加密密钥材料存储在文件外部。

4.4 附加认证数据(AAD)

Parquet 使用 AAD 防止文件被替换。例如: - 文件交换保护:通过 AAD 前缀唯一标识文件,避免文件被旧版本替换。 - 模块交换保护:AAD 后缀由 Parquet 内部构建,防止同一文件内或不同文件间的模块被替换。

5 文件格式

5.1 加密模块的序列化

加密数据存储格式如下:

|长度 (4 字节) | 随机数 (12 字节) | 密文 (长度-28 字节) | 认证标签 (16 字节) |

5.2 加密 Thrift 结构

struct AesGcmV1 {
  1: optional binary aad_prefix
  2: optional binary aad_file_unique
  3: optional bool supply_aad_prefix
}

union EncryptionAlgorithm {
  1: AesGcmV1 AES_GCM_V1
  2: AesGcmCtrV1 AES_GCM_CTR_V1
}

5.3 敏感元数据的保护

如果列和文件尾使用相同的密钥加密,则 ColumnMetaData 默认受到保护。如果列密钥与文件尾密钥不同,或者仅加密列而未加密文件尾,则 ColumnMetaData 需要单独加密并存储在 encrypted_column_metadata 字段中。

5.4 加密文件尾模式

在此模式下,文件尾使用 AES GCM 加密,并存储 FileCryptoMetaData,同时文件格式的魔术字节由 PAR1 变为 PARE 以指示加密状态。

5.5 明文文件尾模式

此模式允许旧版 Parquet 读取器访问未加密的列,同时保护敏感列的统计信息,并使用 AES GCM 签名防止文件尾被篡改。

6 加密开销

加密对存储的开销极小,每 30,000 字节的原始数据增加约 1 字节的加密开销。吞吐量开销取决于 AES 加密是否使用了硬件加速。


最佳实践

  1. 优先使用 AES GCM 模式,确保数据的完整性和机密性。
  2. 对于高性能需求的应用,如果可接受完整性验证的权衡,可以考虑使用 AES_GCM_CTR_V1。
  3. 建议对包含敏感数据的列和文件尾同时加密,确保数据和元数据的安全性。
  4. 使用 AAD 保护文件完整性,防止文件替换和数据篡改。