资讯动态

如何用 PyArrow 写入和读取 Parquet 列级加密文件

发布时间:2026/9/15 12:10:35 来源:尧图企业网站定制
如何用 PyArrow 写入和读取 Parquet 列级加密文件【免费下载链接】arrowApache Arrow is the universal columnar format and multi-language toolbox for fast data interchange and in-memory analytics项目地址: https://gitcode.com/GitHub_Trending/arrow3/arrowApache Parquet 支持列级加密文档中称为 Parquet Modular Encryption / Columnar Encryption可以让文件的不同列使用不同的主加密密钥保护。Parquet 列加密在 Apache Arrow 4.0.0 起支持 CPyArrow 自 6.0.0 起可用。本文介绍如何用 PyArrow 完成两件事把一张表写成按列加密的 Parquet 文件以及用解密密钥把它读回来并核对数据一致。准备条件已安装 PyArrow 6.0.0 或更高版本。如果pyarrow是通过 pip 或 conda 安装的Parquet 支持已包含在内可以直接import pyarrow.parquet as pq。如果从源码构建pyarrow编译 C 库时除了-DARROW_PARQUETON还必须加-DPARQUET_REQUIRE_ENCRYPTIONON否则没有 Parquet 加密能力详见 Python 构建文档 和 Parquet 文档首页。Parquet 采用信封加密envelope encryption文件的各部分用随机生成的数据加密密钥DEK加密DEK 再由密钥管理服务KMS中的主加密密钥MEK包装。因此有两条写入/读取路径KMS 流程CryptoFactory主密钥存放在你组织内的 KMS 中支持按列指定不同的主密钥即真正的列级加密直连密钥流程create_encryption_properties/create_decryption_properties跳过 KMS直接用明文密钥但只支持统一加密footer 和所有列共用一把密钥不支持按列分密钥。路径一通过 KMS 实现按列加密1. 实现一个 KmsClientpyarrow.parquet.encryption.KmsClient定义了一个非正式接口你的 KMS 客户端需要实现wrap_key用主密钥包装 DEK和unwrap_key解包两个方法。仓库中提供了一个基于 HashiCorp Vault 的完整示例见 sample_vault_kms_client.py。文档给出的骨架如下省略号部分是调用你自己 KMS 的代码import pyarrow.parquet.encryption as pe class MyKmsClient(pe.KmsClient): An example KmsClient implementation skeleton def __init__(self, kms_connection_configuration): pe.KmsClient.__init__(self) # 基于 kms_connection_configuration 做 KMS 相关初始化 def wrap_key(self, key_bytes, master_key_identifier): wrapped_key ... # 调用 KMS用 master_key_identifier 指定的密钥包装 key_bytes return wrapped_key def unwrap_key(self, wrapped_key, master_key_identifier): key_bytes ... # 调用 KMS用 master_key_identifier 指定的密钥解包 wrapped_key return key_bytes文档同时提醒生产环境的 KMS 客户端应与组织的安全管理员合作设计由有访问控制管理经验的开发者构建仓库中的 Vault 示例明确标注 Not for production use!只作为接口参照。2. 配置 KMS 连接与加密方案具体客户端类在运行时由你提供的工厂函数加载。连接配置通过pe.KmsConnectionConfig传入选项包括kms_instance_urlKMS 实例 URLkms_instance_id使用的 KMS 实例 ID存在多个实例时key_access_token传给 KMS 的授权 tokencustom_kms_confKMS 类型相关的自定义配置字符串字典。加密方案通过pe.EncryptionConfiguration描述关键选项footer_key用于加密/签名 footer 的主密钥 IDcolumn_keys哪些列用哪个主密钥加密字典的主密钥 ID 为键、列名列表为值例如{key1: [col1, col2], key2: [col3]}未列出的列保持明文uniform_encryptionfooter 和所有列都用footer_key加密不能与column_keys同时使用encryption_algorithmAES_GCM_V1默认或AES_GCM_CTR_V1plaintext_footerfooter 是否以明文写入否则加密internal_key_material密钥材料是否存于文件 footer设为false时存放在同目录的独立文件中从而支持密钥轮换还有double_wrapping、cache_lifetime、data_key_length_bitsDEK 长度128/192/256 位等可选项。对于 struct/map 等嵌套字段列配置根列名会加密该列下所有嵌套字段只加密个别叶子字段时struct 列s的内字段f写作s.fmap 列m的键值字段约定为m.key_value.key和m.key_value.value。3. 写入加密文件import pyarrow.parquet as pq import pyarrow.parquet.encryption as pe def kms_client_factory(kms_connection_configuration): return MyKmsClient(kms_connection_configuration) crypto_factory pe.CryptoFactory(kms_client_factory) kms_connection_config pe.KmsConnectionConfig( kms_instance_url..., # 你的 KMS 实例 URL key_access_token..., # 你的 KMS 授权 token ) encryption_config pe.EncryptionConfiguration( footer_keyfooter_key_name, column_keys{ column_key_name: [Column1, Column2], }, ) encryption_properties crypto_factory.file_encryption_properties( kms_connection_config, encryption_config) with pq.ParquetWriter(filename, schema, encryption_propertiesencryption_properties) as writer: writer.write_table(table)其中filename、schema、table是你要写入的文件名、Arrow schema 和数据表。仓库的 Vault 示例给出了可直接运行的完整版本设置环境变量VAULT_URL和VAULT_TOKEN并在 Vault 中启用 transit engine 后示例用footer_key、col_a_key、col_b_key三把主密钥分别加密 footer、列a、列b列c保持明文。4. 读取加密文件并验证读取时用file_decryption_properties构造解密属性传给pq.ParquetFiledecryption_properties crypto_factory.file_decryption_properties( kms_connection_config) parquet_file pq.ParquetFile(filename, decryption_propertiesdecryption_properties) result_table parquet_file.read()验证方式参照仓库示例的写法读回后与原表做等值断言——assert table.equals(result_table)Vault 示例的parquet_write_read_with_vault就是加密写入 → 解密读取 →assert table.equals(result_table)这条完整链路可作为当前场景的核对基准。路径二直连密钥不经过 KMS如果不需要 KMS、也不需要按列分密钥可以用低层 API 直接从明文密钥构造加密/解密属性。注意两点限制只支持统一加密传入的密钥同时用于 footer 和所有列按列分密钥必须走上面的CryptoFactory流程文档提示多文件复用同一把密钥而没有唯一数据密钥会削弱 AES-GCM 安全性调用方需自行负责密钥管理实践。写入import pyarrow as pa import pyarrow.parquet as pq import pyarrow.parquet.encryption as pe table pa.table({col: [1, 2, 3]}) props pe.create_encryption_properties( footer_keyb0123456789abcdef, # 必须 16/24/32 字节对应 AES-128/192/256 aad_prefixbtable_id, store_aad_prefixFalse, ) pq.write_table(table, encrypted.parquet, encryption_propertiesprops)读取aad_prefix必须与写入时一致尤其是写入时store_aad_prefixFalse的情况下decryption_props pe.create_decryption_properties( footer_keyb0123456789abcdef, aad_prefixbtable_id, ) result pq.read_table(encrypted.parquet, decryption_propertiesdecryption_props)相关参数说明create_encryption_properties的aad_prefix为可选的认证数据前缀store_aad_prefix控制是否把该前缀存入文件元数据置False时表示前缀将在读取时由调用方提供encryption_algorithm可选AES_GCM_V1默认或AES_GCM_CTR_V1plaintext_footerTrue时 footer 不加密schema 和元数据无需密钥即可读取create_decryption_properties的check_footer_integrity默认为True校验 footer 签名文档建议只在调试时置Falseallow_plaintext_files默认False控制是否允许用解密属性读取明文文件而不报错。密钥轮换可选如果写入时设置internal_key_materialFalse密钥材料存放在 Parquet 文件旁的独立文件中而不是 footer 里此时可以用crypto_factory.rotate_master_keys把外部密钥材料重新包装到新主密钥下覆盖外部密钥材料文件而无需改动 Parquet 文件本身crypto_factory.rotate_master_keys( kms_connection_config, parquet_file_pathtable.parquet, )限制小结列级按列分密钥加密只存在于 KMS 流程直连密钥函数目前只支持统一加密无法解密按列分密钥的文件源码 docstring 中明确说明 files encrypted with per-column keys cannot be decrypted using this function。仓库中的 Vault KMS 客户端示例仅供接口参照非生产可用。加密属性可传给pq.write_table/pq.ParquetWriter和pq.read_table/pq.ParquetFile两者分别对应写入和读取路径参数名分别是encryption_properties和decryption_properties。更多细节可参考 Parquet 加密文档。【免费下载链接】arrowApache Arrow is the universal columnar format and multi-language toolbox for fast data interchange and in-memory analytics项目地址: https://gitcode.com/GitHub_Trending/arrow3/arrow创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

读完文章,也想定制专属网站?

尧图设计师 24 小时内与您沟通定制方案

免费获取报价