Manage client-side encrypted files with the Drive API

Client-side encryption (CSE) ensures that your data is encrypted before it reaches Drive servers, giving you control over your data. This guide walks you through the process of programmatically encrypting and uploading, as well as downloading and decrypting, CSE files using the Drive API. It also covers recommended approaches for testing and validating your implementation.

Before you begin

Before you manage encrypted files, set up your Google Workspace domain using the following checklist:

Authentication and authorization

To interact with the Drive API and your KACLS, you must choose an authentication method. This choice affects how you interact with both services:

For additional details regarding creating credentials, see the Create access credentials guide.

Domain IdP Authentication

To authenticate with your IdP, you must configure an OAuth client ID and download its client secret file. Your application must obtain an authentication token from your IdP to authenticate requests to your KACLS. This token is required to allow your application access to the Data Encryption Key.

Handle credentials securely

Your application handles sensitive credentials for authenticating to the Drive API and your IdP. These include:

  • Secret material from the IdP, such as a client-secret-file
  • Secret material from Google, such as a service-account-private-key-file
  • Secret material stored by the app, such as saved-credentials

You must ensure that all of these credentials are stored securely.

Limits and quotas

Client-side encrypted files are subject to standard Drive limits and quotas. Be aware of shared drive limits, general file and folder limits, and how to manage your quota. Additionally, your import tool must handle rate limits from your Key Access Control List Service (KACLS) and your Identity Provider (IdP).

Encrypted file structure

Drive expects the following client-side encrypted file format for uploads and downloads.

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

Magic header

A magic header (also known as a file signature or magic number) is a constant byte sequence placed at the very beginning of a file to uniquely identify its format. The file must begin with the bytes 0x99 0x5E 0xCC 0x5E.

Encrypted chunks

The file must be split into 2MiB chunks. Each chunk is encrypted using the Google Tink library's Authenticated Encryption with Associated Data (AEAD) primitive with an AES-GCM key type, using the chunk index and a final chunk flag as the Associated Data. For a code example that uses the Drive API and conforms to this specification, see the open source demo.

Encrypt and upload a file

To upload a CSE file, your application must authenticate, request a CSE token, encrypt the file content locally, wrap the encryption key, and finally upload the encrypted content and metadata to Google Drive.

Obtain a CSE token

Request a CSE token from Google Drive by calling the Drive API Files:generateCseToken method. Ensure that you don't include the fileId query parameter in the request. To create the file in a specific folder, include the parent query parameter with the folder ID. If parent is omitted, the file is created in the user's root My Drive folder. The response includes a unique file ID for the upload and a JWT authorization token, which is required for the key wrapping step.

Encrypt data locally

  1. Use Google Tink to generate a unique Data Encryption Key (DEK) for the file.
  2. Encrypt the file content according to the encrypted file structure.

Compute Resource Key Hash

To compute the resource key hash:

  1. Extract the resource_name and perimeter_id from the jwt authorization token received from generateCseToken. If perimeter_id is missing, use an empty string.
  2. Calculate HMAC-SHA256 using the plaintext DEK as the key and the string ResourceKeyDigest:my_resource_name:my_perimeter_id as the data to sign.
  3. Base64-encode the resulting hash.

For more details, see Resource Key Hash.

Wrap the encryption key

To protect the DEK, encrypt (wrap) it using your external KACLS.

  1. Call the appropriate endpoint:
  2. Pass the plaintext DEK, your IdP authentication token, the Google authorization token (if required), the resource_name from the JWT, and a reason.
  3. Receive the Wrapped DEK (WDEK) from the KACLS.

Upload to Drive

Use the Drive API files.create endpoint to perform a standard file upload of the encrypted file blob. Set the following fields in the file metadata:

  • id: The unique file ID received from the generateCseToken response.
  • mimeType: application/vnd.google-gsuite.encrypted; content="application/octet-stream".
    • The content parameter can be set to the original file's MIME type.
  • clientEncryptionDetails:
    • encryptionState: "encrypted".
    • decryptionMetadata:
      • wrappedKey: The Wrapped DEK (WDEK) received from the KACLS.
      • kaclsId: The KACLS ID received from the generateCseToken response.
      • keyFormat: "tinkAesGcmKey".
      • aes256GcmChunkSize: "default".
      • encryptionResourceKeyHash: The hash computed in Compute Resource Key Hash.

Open source example

For a practical demonstration of the encrypt and upload process, refer to the open source demo. This provides a working solution and can serve as a valuable reference.

Download and decrypt a file

Downloading a CSE file requires retrieving the encrypted content and metadata from Google Drive, requesting the plaintext DEK from your KACLS, and decrypting the file locally.

Retrieve file metadata and encrypted content

Call the Drive API Files:get method to retrieve the file's metadata and content. The clientEncryptionDetails contains the DecryptionMetadata which includes the Wrapped DEK (WDEK) and the JWT containing the KACLS information.

Unwrap the encryption key

  1. Call the appropriate endpoint:
  2. Pass the WDEK, your IdP authentication token, the Google authorization token (if required), the resource_name, and a reason.
  3. Receive the plaintext DEK from the KACLS.

Decrypt data locally

  1. Initialize the cipher using the plaintext DEK received from the KACLS.
  2. Skip the initial magic bytes and decrypt the remaining content according to the encrypted file structure.

Open source example

For a practical demonstration of the download and decrypt process, refer to the open source demo. This provides a working solution and can serve as a valuable reference.

Validate imported files

Because Google doesn't have access to the encryption keys, Google cannot decrypt and validate your files server-side. Implementation errors during the local encryption or key wrapping phases will result in errors when client-side decrypting files. Thorough validation is critical before utilizing your own implementation.

For uploaded Google Drive CSE content to function correctly, it must be properly encrypted and contain the correct metadata. You are responsible for ensuring that the content is valid and can be decrypted.

Perform roundtrip encryption and decryption tests

To validate your implementation, it's crucial to test the end-to-end flow. This involves taking a set of test files, encrypting them using your local logic, uploading them to Drive using the API, and then downloading and decrypting them. After decryption, compare the resulting content with the original files to ensure they are identical. This process helps catch any issues in the encryption, key wrapping, or metadata handling. The open source demo demonstrates how you can implement such a validation process within your own application.

Spot-checking with Google Drive

Verify that the uploaded files include a lock icon in the Drive web client. Manually download a small number of uploaded files to verify they function as expected. This check uses Google's CSE implementation to attempt decryption, helping to isolate issues in your encryption or key wrapping logic. Include files from both My Drive and Shared drives.

Open source demo

The open source Drive CSE Upload package provides a complete, working Python library and command-line example that implements the CSE upload and download flows described in this guide. Reviewing the demo code is highly recommended before building your own CSE integration.