You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在GCP上使用Python实现Tink的确定性AEAD信封加密?

Python实现GCP KMS + Tink确定性AEAD信封加密

前置准备

  • 安装依赖包:
    pip install tink google-cloud-kms
    
  • 确保环境已配置GCP认证(比如通过gcloud auth application-default login或服务账号密钥文件)
  • 在GCP KMS中创建好密钥环和对称加密密钥(作为KEK),记录密钥资源路径(格式如projects/[PROJECT_ID]/locations/[LOCATION]/keyRings/[KEY_RING]/cryptoKeys/[CRYPTO_KEY])

完整代码示例

import tink
from tink import daead
from google.cloud import kms_v1

# 初始化Tink的确定性AEAD模块
daead.register()

def generate_dek() -> bytes:
    """生成数据加密密钥(DEK),使用Tink的AES-SIV确定性AEAD模板"""
    key_template = daead.deterministic_aead_key_templates.AES256_SIV
    keyset_handle = tink.new_keyset_handle(key_template)
    # 将DEK序列化为二进制格式
    return keyset_handle.write_to_bytes()

def encrypt_dek_with_kms(kms_client: kms_v1.KeyManagementServiceClient, kek_path: str, dek: bytes) -> bytes:
    """使用GCP KMS中的KEK加密DEK"""
    encrypt_response = kms_client.encrypt(
        request={"name": kek_path, "plaintext": dek}
    )
    return encrypt_response.ciphertext

def decrypt_dek_with_kms(kms_client: kms_v1.KeyManagementServiceClient, kek_path: str, encrypted_dek: bytes) -> bytes:
    """使用GCP KMS中的KEK解密DEK"""
    decrypt_response = kms_client.decrypt(
        request={"name": kek_path, "ciphertext": encrypted_dek}
    )
    return decrypt_response.plaintext

def encrypt_data(dek_plaintext: bytes, data: bytes) -> bytes:
    """使用确定性AEAD加密数据"""
    # 从DEK明文初始化确定性AEAD实例
    keyset_handle = tink.read_keyset_handle_from_bytes(dek_plaintext)
    daead_primitive = keyset_handle.primitive(daead.DeterministicAead)
    # 加密数据,可传入关联数据作为第二个参数,示例中为空
    ciphertext = daead_primitive.encrypt_deterministically(data, b"")
    return ciphertext

def decrypt_data(encrypted_dek: bytes, kek_path: str, ciphertext: bytes) -> bytes:
    """解密流程:先解密DEK,再用确定性AEAD解密数据"""
    kms_client = kms_v1.KeyManagementServiceClient()
    # 解密DEK
    dek_plaintext = decrypt_dek_with_kms(kms_client, kek_path, encrypted_dek)
    # 初始化确定性AEAD实例
    keyset_handle = tink.read_keyset_handle_from_bytes(dek_plaintext)
    daead_primitive = keyset_handle.primitive(daead.DeterministicAead)
    # 解密数据,需与加密时的关联数据一致
    plaintext = daead_primitive.decrypt_deterministically(ciphertext, b"")
    return plaintext

if __name__ == "__main__":
    # 替换为你的GCP KMS密钥路径
    KEK_PATH = "projects/your-project-id/locations/us-central1/keyRings/your-keyring/cryptoKeys/your-kek"
    
    # 加密流程示例
    kms_client = kms_v1.KeyManagementServiceClient()
    dek_plaintext = generate_dek()
    encrypted_dek = encrypt_dek_with_kms(kms_client, KEK_PATH, dek_plaintext)
    original_data = b"your-sensitive-data-here"
    ciphertext = encrypt_data(dek_plaintext, original_data)
    
    print(f"加密后的DEK: {encrypted_dek.hex()}")
    print(f"密文: {ciphertext.hex()}")
    
    # 解密流程示例
    decrypted_data = decrypt_data(encrypted_dek, KEK_PATH, ciphertext)
    print(f"解密后的数据: {decrypted_data.decode('utf-8')}")

关键说明

  • 确定性AEAD选择:示例使用AES256_SIV模板,这是Tink推荐的确定性AEAD算法,支持关联数据绑定,安全性符合行业标准。
  • 信封加密核心流程:
    1. 生成一次性DEK(仅在内存中存在明文,不落地存储)
    2. 用GCP KMS的KEK加密DEK,加密后的DEK可与密文一同持久化
    3. 使用DEK初始化的确定性AEAD实例加密原始数据
    4. 解密时先通过KMS还原DEK明文,再用其解密密文
  • 安全注意事项:
    • 严格限制GCP KMS密钥的访问权限,仅授权必要服务账号
    • 关联数据(AD)可用于绑定密文的上下文场景,实际使用中可按需添加
    • DEK明文仅在内存中临时存在,避免日志或内存dump泄露

内容的提问来源于stack exchange,提问作者Balázs Tóth

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.16 17:20:45