This page describes how to implement client-side encryption on Cloud SQL.
Overview
Client-side encryption is the act of encrypting data before writing it to Cloud SQL. You can encrypt Cloud SQL data in a manner that only your application can decrypt.
To enable client-side encryption you have the following options:
- Using an encryption key stored in the Cloud Key Management Service (Cloud KMS).
- Using an encryption key stored locally in your application.
In this topic, we describe how to use the first option, which provides the most seamless key management option. We create an encryption key in Cloud KMS and implement envelope encryption using Tink, Google's open source cryptographic library.
Why do you need client-side encryption?
You need client-side encryption if you want to protect Cloud SQL data at the column level 1. Imagine you have a table of names and credit card numbers. You want to grant a user access to this table, but you don't want them to view the credit card numbers. You can encrypt the numbers using client-side encryption. As long as the user is not granted access to the encryption key in Cloud KMS, they can't read the credit card information.
Create keys using Cloud KMS
Cloud KMS lets you create and manage keys on Google Cloud Platform.
Cloud KMS supports many different key types. For client-side encryption, you need to create a symmetric key.
To give your application access to the key in Cloud KMS, you need to
grant the service account that your application uses with the
cloudkms.cryptoKeyEncrypterDecrypter
role. In gcloud, you use the following
command to do this:
gcloud kms keys add-iam-policy-binding key \ --keyring=key-ring \ --location=location \ --member=serviceAccount:service-account-name@example.domain.com \ --role=roles/cloudkms.cryptoKeyEncrypterDecrypter
While you can use the KMS key to directly encrypt data, here we use a more flexible solution called envelope encryption. This allows us to encrypt messages longer than 64KB, which is the maximum message size that the Cloud Key Management Service API can support.
Cloud KMS envelope encryption
In envelope encryption, the KMS key acts as a key encrypting key (KEK). That is, it is 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 need to:
- Generate a data encryption key (DEK) locally.
- Use this DEK locally to encrypt the message.
- Call Cloud KMS to encrypt (wrap) the DEK with the KEK.
- Store the encrypted data and the wrapped DEK.
Instead of implementing envelope encryption from scratch, in this topic we use Tink.
Tink
Tink is a multi-language, cross-platform library that provides high-level cryptographic APIs. To encrypt data with Tink's envelope encryption, you provide Tink with a key URI pointing to your KEK in Cloud KMS, and credentials that allow Tink to use the KEK. Tink generates the DEK, encrypts the data, wraps the DEK and returns a single ciphertext with the encrypted data and wrapped DEK.
Tink supports envelope encryption in C++, Java, Go, and Python using the AEAD API:
public interface Aead{
byte[] encrypt(final byte[] plaintext, final byte[] associatedData)
throws…
byte[] decrypt(final byte[] ciphertext, final byte[] associatedData)
throws…
}
Besides the normal message/ciphertext argument, the encrypt and decrypt methods
support optional associated data. This argument can be used to tie the
ciphertext to a piece of data. For example, suppose you have a database with a
field user-id
and a field encrypted-medical-history
. In this case, the field
user-id
should probably be used as associated data when encrypting the medical
history. This ensures that an attacker cannot move medical history from one user
to another. It is also used to verify that you have the correct row of data when
you run a query.
Samples
In this section, we'll walk through sample code for a voter information database that uses client-side encryption. The sample code shows how to:
- Create a database table and connection pool
- Set up Tink for envelope encryption
- Encrypt and decrypt data using Tink's envelope encryption with a KEK in Cloud KMS
Before you begin
Create a Cloud SQL Instance by following these instructions. Note the connection string, database user, and database password that you create.
Create a database for your application by following these instructions. Note the database name.
Create a KMS key for your application by following these instructions. Copy the resource name of your created key.
Create a service account with the 'Cloud SQL Client' permissions by following these instructions.
Add the 'Cloud KMS CryptoKey Encrypter/Decrypter' permission for the key to your service account by following these instructions.