使用 Drive API 管理客户端加密的文件

客户端加密功能 (CSE) 可确保您的数据在到达云端硬盘服务器之前已加密,让您能够掌控自己的数据。本指南将逐步介绍如何使用 Drive API 以编程方式加密和上传 CSE 文件,以及下载和解密 CSE 文件。此外,还介绍了用于测试和验证实现情况的推荐方法。

准备工作

在管理加密文件之前,请使用以下核对清单设置您的 Google Workspace 网域:

身份验证和授权

如需与 Drive API 和 KACLS 进行交互,您必须选择一种身份验证方法。此选择会影响您与这两项服务的互动方式:

  • 个人:如需以个人身份进行身份验证,请使用 OAuth 流程代表该用户执行操作。使用标准 /wrap/unwrap 端点,并提供相应用户的 Google 授权令牌。
  • 管理员:如需模拟网域中的其他用户,请使用具有全网域授权 (DWD) 的服务账号。使用 /privilegedwrap/privilegedunwrap 端点,而无需 Google 授权令牌。

如需详细了解如何创建凭据,请参阅创建访问凭据指南。

网域 IdP 身份验证

如需通过 IdP 进行身份验证,您必须配置 OAuth 客户端 ID 并下载其客户端密钥文件。您的应用必须从 IdP 获取身份验证令牌,才能对 KACLS 的请求进行身份验证。此令牌是必需的,用于允许您的应用访问数据加密密钥

安全地处理凭据

您的应用会处理敏感凭据,以便向 Drive API 和您的 IdP 进行身份验证。其中包括:

  • 来自 IdP 的 Secret 材料,例如 client-secret-file
  • 来自 Google 的 Secret 材料,例如 service-account-private-key-file
  • 应用存储的 Secret 材料,例如已保存的凭据

您必须确保所有这些凭据都得到安全存储。

限制和配额

客户端加密的文件受标准云端硬盘限制和配额的约束。请注意共享云端硬盘限制、常规文件和文件夹限制以及如何管理配额。 此外,您的导入工具必须能够处理密钥访问控制列表服务 (KACLS) 和身份提供方 (IdP) 的速率限制。

加密文件结构

云端硬盘要求上传和下载的客户端加密文件采用以下格式。

+-------------------+
| Magic header      |
+-------------------+
| Encrypted Chunk 1 |
+-------------------+
| Encrypted Chunk 2 |
+-------------------+
| ...               |
+-------------------+
| Encrypted Chunk N |
+-------------------+

Magic 标头

magic header(也称为文件签名或 magic number)是放置在文件开头的常量字节序列,用于唯一标识文件格式。文件必须以字节 0x99 0x5E 0xCC 0x5E 开头。

加密的块

文件必须拆分为 2 MiB 的块。每个块都使用 Google Tink 库的经过身份验证的关联数据加密 (AEAD) 原语(采用 AES-GCM 密钥类型)进行加密,并使用块索引和最终块标志作为关联数据。如需查看使用 Drive API 并符合此规范的代码示例,请参阅开源演示

加密并上传文件

如需上传 CSE 文件,您的应用必须进行身份验证、请求 CSE 令牌、在本地加密文件内容、封装加密密钥,最后将加密的内容和元数据上传到 Google 云端硬盘。

获取 CSE 令牌

通过调用 Drive API Files:generateCseToken 方法,从 Google 云端硬盘请求 CSE 令牌。确保您未在请求中添加 fileId 查询参数。如需在特定文件夹中创建文件,请添加包含文件夹 ID 的 parent 查询参数。如果省略 parent,则会在用户的根“我的云端硬盘”文件夹中创建文件。响应包含上传的唯一文件 ID 和 JWT 授权令牌,后者是密钥封装步骤所必需的。

在本地加密数据

  1. 使用 Google Tink 为文件生成唯一的数据加密密钥 (DEK)。
  2. 根据加密文件结构加密文件内容。

计算资源密钥哈希值

如需计算资源键哈希值,请执行以下操作:

  1. generateCseToken 收到的 jwt 授权令牌中提取 resource_nameperimeter_id。如果未提供 perimeter_id,则使用空字符串。
  2. 使用明文 DEK 作为密钥,并使用字符串 ResourceKeyDigest:my_resource_name:my_perimeter_id 作为要签名的数据,计算 HMAC-SHA256。
  3. 对生成的哈希进行 Base64 编码。

如需了解详情,请参阅资源密钥哈希

封装加密密钥

为了保护 DEK,请使用外部 KACLS 对其进行加密(封装)。

  1. 调用相应的端点:
  2. 传递纯文本 DEK、您的 IdP 身份验证令牌、Google 授权令牌(如果需要)、JWT 中的 resource_namereason
  3. 从 KACLS 接收封装的 DEK (WDEK)。

上传到云端硬盘

使用 Drive API files.create 端点执行加密文件 blob 的标准文件上传。在文件元数据中设置以下字段:

  • id:从 generateCseToken 响应中收到的唯一文件 ID。
  • mimeTypeapplication/vnd.google-gsuite.encrypted; content="application/octet-stream"
    • content 参数可以设置为原始文件的 MIME 类型。
  • clientEncryptionDetails:
    • encryptionState"encrypted"
    • decryptionMetadata:
      • wrappedKey:从 KACLS 收到的封装 DEK (WDEK)。
      • kaclsId:从 generateCseToken 响应中收到的 KACLS ID。
      • keyFormat"tinkAesGcmKey"
      • aes256GcmChunkSize"default"
      • encryptionResourceKeyHash:在 Compute Resource Key Hash 中计算的哈希值。

开源示例

如需查看加密和上传流程的实际演示,请参阅开源演示。这提供了一个可行的解决方案,可作为有价值的参考。

下载并解密文件

下载 CSE 文件需要从 Google 云端硬盘检索加密的内容和元数据,从 KACLS 请求纯文本 DEK,然后在本地解密文件。

检索文件元数据和加密内容

调用 Drive API Files:get 方法来检索文件的元数据和内容。clientEncryptionDetails 包含 DecryptionMetadata,其中包括封装的 DEK (WDEK) 和包含 KACLS 信息的 JWT。

解封装加密密钥

  1. 调用相应的端点:
  2. 传递 WDEK、您的 IdP 身份验证令牌、Google 授权令牌(如果需要)、resource_namereason
  3. 从 KACLS 接收纯文本 DEK。

在本地解密数据

  1. 使用从 KACLS 收到的明文 DEK 初始化加密器。
  2. 跳过初始 magic 字节,并根据加密文件结构解密剩余内容。

开源示例

如需查看下载和解密流程的实际演示,请参阅开源演示。这提供了一个可行的解决方案,可作为有价值的参考。

验证导入的文件

由于 Google 无法访问加密密钥,因此无法在服务器端解密和验证您的文件。在本地加密或密钥封装阶段出现实现错误会导致在客户端解密文件时出现错误。在利用自己的实现之前,请务必进行全面验证。

为了使上传的 Google 云端硬盘 CSE 内容正常运行,必须对其进行正确加密并包含正确的元数据。您有责任确保内容有效且可以解密。

执行往返加密和解密测试

如需验证您的实现,请务必测试端到端流程。这包括获取一组测试文件,使用本地逻辑对其进行加密,使用 API 将其上传到云端硬盘,然后下载并解密这些文件。解密后,将生成的内容与原始文件进行比较,以确保它们完全相同。此流程有助于发现加密、密钥封装或元数据处理方面的任何问题。开源演示展示了如何在您自己的应用中实现此类验证流程。

使用 Google 云端硬盘进行抽查

验证上传的文件在云端硬盘网页版客户端中是否包含锁定图标。手动下载少量已上传的文件,以验证它们是否按预期运行。此检查使用 Google 的 CSE 实现来尝试解密,有助于隔离加密或密钥封装逻辑中的问题。包含我的云端硬盘共享云端硬盘中的文件。

开源演示

开源 Drive CSE Upload 软件包提供了一个完整的实用 Python 库和命令行示例,实现了本指南中介绍的 CSE 上传和下载流程。强烈建议您在构建自己的 CSE 集成之前先查看演示代码。