このページでは、Cloud SQL でクライアントサイド暗号化を実装する方法について説明します。
概要
クライアントサイド暗号化では、データを暗号化した後、Cloud SQL に書き込みます。Cloud SQL データをそのように暗号化することで、アプリケーションだけが復号できます。
クライアントサイド暗号化を有効にするには、次の選択肢があります。
- Cloud Key Management Service(Cloud KMS)に保存された暗号鍵を使用する。
- アプリケーションにローカルに保存された暗号鍵を使用する。
このトピックでは、最初の手段の使用について説明します。これによって、非常にシームレスな鍵管理手段が実現されます。Cloud KMS で暗号鍵を作成し、Tink(Google のオープンソース暗号ライブラリ)を使用してエンベロープ暗号化を実装します。
クライアントサイド暗号化が必要な理由
列レベル 1 で Cloud SQL データを保護する場合は、クライアントサイド暗号化が必要です。名前とクレジット カード番号のテーブルがあるとします。ユーザーにこのテーブルへのアクセス権を付与しますが、クレジット カード番号は表示したくありません。クライアントサイド暗号化を使用することで、番号を暗号化できます。ユーザーは、Cloud KMS の暗号鍵に対するアクセス権を持たない限り、クレジット カード情報を読み取ることができません。
Cloud KMS を使用して鍵を作成する
Cloud KMS を使用すると、Google Cloud Platform 上で鍵を作成して管理できます。
Cloud KMS は、さまざまな種類の鍵をサポートしています。クライアントサイド暗号化では、対称鍵を作成する必要があります。
アプリケーションが Cloud KMS の鍵にアクセスできるようにするには、アプリケーションが使用するサービス アカウントに cloudkms.cryptoKeyEncrypterDecrypter
ロールを付与する必要があります。gcloud では、次のコマンドを使用して実施します。
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
KMS 鍵を使用してデータの暗号化を直接実行することもできますが、ここではエンベロープ暗号化というさらに柔軟な解決策を使用します。これにより、Cloud Key Management Service API がサポートできる最大メッセージ サイズの 64 KB を超えるメッセージを暗号化できます。
Cloud KMS のエンベロープ暗号化
エンベロープ暗号化では、KMS 鍵は鍵暗号鍵(KEK)として機能します。つまり、実際のデータの暗号化に使用されるデータ暗号鍵(DEK)の暗号化に使用されます。
Cloud KMS で KEK を作成した後、各メッセージを暗号化するには、次のことを行う必要があります。
- データ暗号鍵(DEK)をローカルで作成します。
- この DEK をローカルで使用してメッセージを暗号化します。
- Cloud KMS を呼び出して KEK を使用して DEK を暗号化(ラップ)します。
- 暗号化されたデータとラップされた DEK を保管します。
エンベロープ暗号化をゼロから実装する代わりに、このトピックでは Tink を使用します。
Tink
Tink は、高レベルの暗号 API を提供する、多言語のクロス プラットフォーム ライブラリです。Tink のエンベロープ暗号化でデータを暗号化するには、Cloud KMS の KEK を指す鍵 URI と、Tink で KEK を使用するための認証情報を指定します。Tink は、DEK を生成し、データの暗号化と DEK のラップを行います。そして、暗号化したデータとラップした DEK を含む単一の暗号テキストを返します。
Tink では、AEAD API を使用した C++、Java、Go、Python のエンベロープ暗号化をサポートしています。
public interface Aead{
byte[] encrypt(final byte[] plaintext, final byte[] associatedData)
throws…
byte[] decrypt(final byte[] ciphertext, final byte[] associatedData)
throws…
}
通常のメッセージ / 暗号テキスト引数に加えて、暗号化と復号の方法では、オプションの関連データもサポートされています。この引数を使用して、暗号テキストをデータと結びつけることができます。たとえば、フィールド user-id
とフィールド encrypted-medical-history
を持つデータベースがあるとします。この場合、医療履歴を暗号化するときに、user-id
フィールドを関連データとして使用することをおすすめします。これにより、攻撃者がユーザー間で医療履歴を移動させることはできません。これは、クエリの実行時に正しいデータの行があるかどうかを確認するためにも使用されます。
サンプル
このセクションでは、クライアントサイド暗号化を使用する有権者情報データベースのサンプルコードについて説明します。このサンプルコードでは、次の処理を行う方法を示します。
- データベース テーブルと接続プールを作成する
- エンベロープ暗号化用に Tink を設定する
- Cloud KMS の KEK で Tink のエンベロープ暗号化を使用してデータを暗号化および復号する
始める前に
こちらの手順に沿って Cloud SQL インスタンスを作成します。作成する接続文字列、データベース ユーザー、データベース パスワードをメモします。
手順に沿って、アプリケーションのデータベースを作成します。データベース名をメモします。
手順に沿って、アプリケーションの KMS 鍵を作成します。作成した鍵のリソース名をメモします。
こちらの手順に沿って、Cloud SQL クライアントの権限でサービス アカウントを作成します。
こちらの手順に沿って、サービス アカウントに、鍵の Cloud KMS 暗号鍵の暗号化 / 復号の権限を追加します。