使用同一Cloud KMS密钥解密BigQuery预加密CSV列的配置问题
核心结论
BigQuery的AEAD.DECRYPT_STRING+KEYS.KEYSET_CHAIN解密链路仅支持Tink加密框架生成的信封加密格式密文,无法直接解密你通过Python原生调用Cloud KMS对称加密接口生成的密文,和你怎么填first_level_keyset、additional_authenticated_data参数没有直接关系。
两个参数的原生定义
这两个参数是为Tink信封加密场景设计的,含义如下:
first_level_keyset:被Cloud KMS中存储的根密钥(KEK)加密后的数据包密钥(DEK)二进制内容,通常以BYTES类型存储在BigQuery表字段中,不是你在KMS中创建的对称密钥本身。这套逻辑是标准信封加密流程:根密钥永远不直接用来加密数据,只用来加解密实际承担数据加密的数据包密钥。additional_authenticated_data:简称AAD,是加密时自定义传入的、参与密文完整性校验的附加数据,解密时必须和加密时传入的值完全一致才能解密成功;如果加密时没有传AAD,这里填空字节串即可。
你当前方案不兼容的根本原因
你现在直接用Python调用Cloud KMS对称加密接口生成的密文,是KMS原生接口返回的标准密文格式,没有走Tink信封加密流程:
- 加密时直接用KMS中的对称密钥作为数据加密密钥,没有生成独立的DEK,自然不存在
first_level_keyset对应的加密后DEK内容,根本无法填写该参数。 - 即使你随意传入值填充参数,
AEAD.DECRYPT_STRING也无法识别KMS原生密文的结构,会直接返回解密失败错误。
符合你需求的落地路径
你要求GCS数据湖、BigQuery中都不存储明文PII,有两种可落地的方案,不需要推翻现有预加密的逻辑:
方案1:调整Python侧加密逻辑适配BigQuery AEAD链路
将Python侧的加密实现替换为Google Tink库,基于你现有的Cloud KMS密钥做信封加密:
- 加密时通过Tink用KMS中的根密钥生成临时DEK,用DEK加密PII列内容,将加密后的DEK、密文按Tink规范序列化后存储到CSV对应列
- CSV加载到BigQuery后,将存储加密后DEK的字段作为
first_level_keyset传入,加密时自定义的AAD值作为additional_authenticated_data传入,即可正常解密
方案2:保留现有Python加密逻辑,换用BigQuery原生KMS解密函数
如果你不想改动已经生成的加密CSV数据,不需要使用KEYS.KEYSET_CHAIN相关逻辑,直接用BigQuery内置的Cloud KMS远程解密函数即可解密KMS原生接口生成的密文,示例代码如下:
DECLARE KMS_RESOURCE_NAME STRING; SET KMS_RESOURCE_NAME = "gcp-kms://projects/<project>/locations/<location>/keyRings/<keyring>/cryptoKeys/<key>"; SELECT id, -- 密文如果是Python侧base64编码后存为字符串的,先做base64解码为BYTES类型再传入解密 KEYS.REMOTE_KEY_DECRYPT( KEYS.REMOTE_KEY(KMS_RESOURCE_NAME), FROM_BASE64(encrypted_name), -- 加密时传了AAD就填对应字节值,没传就填b"" b"" ) AS decrypted_name FROM `mydataset.mytable`
内容的提问来源于stack exchange,提问作者emp
相关产品推荐
相关产品推荐

