Client-side encryption with Tink and Cloud KMS

This topic describes how to encrypt data locally and upload it to Cloud Storage with Tink and Cloud Key Management Service (Cloud KMS). Tink is an open source cryptography library written by cryptographers and security engineers at Google.

Overview

Client-side encryption is any encryption performed prior to sending your data to the cloud. When using client-side encryption, you're responsible for creating and managing your encryption keys and encrypting your data before sending it to the cloud.

In this topic, you implement client-side envelope encryption with Tink using an encryption key in Cloud KMS.

You can find a Terraform-based blueprint version of this tutorial in the kms-solutions GitHub repository.

Before you begin

  1. Create a symmetric Cloud KMS encryption key for encryption. Take note of the URI of the key. You need it later.
  2. Install Tink for use with Cloud KMS.
  3. Create a bucket in Cloud Storage to upload your encrypted data.

Required roles

To ensure that your service account has the necessary permissions to use Cloud KMS keys with Tink, ask your administrator to grant the Cloud KMS CryptoKey Encrypter/Decrypter (roles/cloudkms.cryptoKeyEncrypterDecrypter) IAM role to your service account on your key.

For more information about granting roles, see Manage access to projects, folders, and organizations.

Your administrator might also be able to give your service account the required permissions through custom roles or other predefined roles.

Envelope encryption with Tink

In envelope encryption, the Cloud KMS key acts as a key encryption key (KEK). That is, it's used to encrypt data encryption keys (DEK) which in turn are used to encrypt actual data.

After creating a KEK in Cloud KMS, to encrypt each message you must:

  1. Generate a data encryption key (DEK) locally.
  2. Use the DEK locally to encrypt the message.
  3. Use Cloud KMS to encrypt (wrap) the DEK with the KEK.
  4. Store the encrypted data and the wrapped DEK.

You don't need to implement this envelope encryption process from scratch when you use Tink.

To use Tink for envelope encryption, you provide Tink with a key URI and credentials. The key URI points to your KEK in Cloud KMS, and the credentials let Tink use the KEK. Tink generates the DEK, encrypts the data, wraps the DEK, and then returns a single ciphertext with the encrypted data and wrapped DEK.

Tink supports envelope encryption in Python, Java, C++, and Go using the Authenticated Encryption with Associated Data (AEAD) primitive.

Connect Tink and Cloud KMS

To encrypt the DEKs generated by Tink with your KEK in Cloud KMS, you need to get the URI of your KEK. In Cloud KMS, the KEK URI has the following format:

gcp-kms://projects/PROJECT_ID/locations/LOCATION/keyRings/KEY_RING/cryptoKeys/KEY_NAME/cryptoKeyVersions/KEY_VERSION

See Getting a Cloud KMS resource ID for details on how to get the path to your key.

Initialize Tink and encrypt data

Tink uses primitives—cryptographic building blocks that manage the details of their underlying algorithms—so you can perform tasks safely. Each primitive offers an API that handles a specific task. Here, we're using AEAD, so we use the Tink AEAD primitive.

Python

Python

To learn how to install and use the client library for Cloud KMS, see Cloud KMS client libraries.

To authenticate to Cloud KMS, set up Application Default Credentials. For more information, see Set up authentication for a local development environment.

"""A command-line utility for performing file encryption using GCS.

It is inteded for use with small files, utilizes envelope encryption and
facilitates ciphertexts stored in GCS.
"""

from absl import app
from absl import flags
from absl import logging
from google.cloud import storage

import tink
from tink import aead
from tink.integration import gcpkms


FLAGS = flags.FLAGS

flags.DEFINE_enum('mode', None, ['encrypt', 'decrypt'],