ビジネス

GCPの「Cloud KMS」をPythonで試してみる

Cloud KMSってどんなサービス?

クラウド上で管理される暗号鍵を使って暗号化/復号/署名といった操作を行えるサービスです。
今回はPythonとgoogle-cloud-kms(クライアントライブラリ)での暗号化と復号を試します。

使用環境

Python 3.8.13
google-cloud-kms 2.11.1

APIの有効化

以降で使用するGCPプロジェクトにおいて事前にAPIを有効化しておく必要があります。
こちらからコンソールへ移動し、APIを有効化することができます。

キーリングの作成

キーリングというのはキーをまとめるためのものです。
現実世界でもキーをリングでまとめたりしますね。GCP世界のキーはキーリングに追加する形で作成できるため、まずはキーリングを作成します。

こちらのキーリングを作成する関数を実行します。

project_id = 'my-project-123'  # GCPプロジェクトのID
location_id = 'asia-northeast1'  # キーリングを作成するロケーション
key_ring_id = 'test-key-ring'  # キーリングを識別するためのID

create_key_ring(project_id, location_id, key_ring_id)

実行すると…

Created key ring: projects/my-project-123/locations/asia-northeast1/keyRings/test-key-ring

と表示され、KMSのコンソールからキーリングを確認できました。


ロケーションについての詳細はこちらをご参照ください。

キーの作成

肝心の暗号鍵を作成します。こちらの関数を実行します。この関数で作成する暗号鍵は対称鍵(共通鍵)です。対称鍵は公開鍵暗号のような非対称暗号よりも高速ですが、暗号化と復号のための鍵が異なる仕組みではないことに注意します。

key_id = 'test-key'  # キーを識別するためのID

create_key_symmetric_encrypt_decrypt(project_id, location_id, key_ring_id, key_id)

実行すると…

Created symmetric key: projects/my-project-123/locations/asia-northeast1/keyRings/test-key-ring/cryptoKeys/test-key

と表示され、KMSのコンソールからキーを確認できました。

暗号化

こちらの関数を実行することで文字列をutf-8でエンコードしてから暗号化できます。リンク先では通信路上でテキストが破損していないことを確認するためにCRC32(チェックサム)の計算をしています。今回はCRC32を利用しないように変更した以下のコードを実行して「Hello, KMS!」の文字列を暗号化しました。

def encrypt_symmetric(project_id, location_id, key_ring_id, key_id, plaintext):
    import base64
    from google.cloud import kms

    # Convert the plaintext to bytes.
    plaintext_bytes = plaintext.encode('utf-8')

    # Create the client.
    client = kms.KeyManagementServiceClient()

    # Build the key name.
    key_name = client.crypto_key_path(project_id, location_id, key_ring_id, key_id)

    # Call the API.
    encrypt_response = client.encrypt(
        request={'name': key_name, 'plaintext': plaintext_bytes}
    )

    print('Ciphertext: {}'.format(base64.b64encode(encrypt_response.ciphertext)))
    return encrypt_response


plaintext = 'Hello, KMS!'

encrypt_symmetric(project_id, location_id, key_ring_id, key_id, plaintext)

すると…

Ciphertext: b’CiQAqIjds4dcBCs0E+Y5yM1APBiab9adFZ0fxsedQQfGtXSBcMQSNABmBwTQt/dVuVcLboQ60tb8bX/BiwmlAS0wnX6i1nfyp9REPkR2lo6dcoeuvs7ADBJc0Jw=’

と表示されました。表示されているのは暗号化後のバイナリをBASE64により文字列にエンコードしたものであることに注意します。

復号

最後に、先程の暗号を復号してみます。こちらの関数を実行することで復号できます。暗号化と同じようにリンク先ではCRC32が利用されています。今回は以下のCRC32を利用しないように変更したものを使用します。

def decrypt_symmetric(project_id, location_id, key_ring_id, key_id, ciphertext):
    from google.cloud import kms

    # Create the client.
    client = kms.KeyManagementServiceClient()

    # Build the key name.
    key_name = client.crypto_key_path(project_id, location_id, key_ring_id, key_id)

    # Call the API.
    decrypt_response = client.decrypt(
        request={'name': key_name, 'ciphertext': ciphertext}
    )

    print('Plaintext: {}'.format(decrypt_response.plaintext))
    return decrypt_response


encrypt_response = encrypt_symmetric(
    project_id, location_id, key_ring_id, key_id, plaintext
)
decrypt_symmetric(
    project_id, location_id, key_ring_id, key_id, encrypt_response.ciphertext
)

これを実行すると…

Ciphertext: b’CiQAqIjds3mxYHcDBly1/OO632EuSHYF3TXmawibmxUd9EDpCEUSNABmBwTQBG3QlWTMjT+0xbLvSzS9fpiuhatBzKKi1nr8ZxvwETJ+wsiLyh1V+vPQUG+vvbU=’
Plaintext: b’Hello, KMS!’

と表示されました。正しく復号して「Hello, KMS!」を表示することができました。

おわりに

今回はCloud KMSによる暗号化/復号を試しました。機密情報は生の状態で保存するのではなく暗号化するとより安全です。Cloud KMSでは鍵をクラウド管理できるので適切に用いれば人為的な流出経路を減らすことができます。また、ローテーションを利用することで流出した場合の被害を抑えることができます。安心して情報を保存・利用するために使ってみてはいかがでしょうか?

Y.N
GRIでデータ分析やアルゴリズム開発、ForecastFlowの開発に携わっています。