こんにちわ! @ktoshi です!
以前、Cloud KMSをGoで使う 記事を書きましたが、今回は PHP(というよりLaravel)で使ってみようと思います。
実際はGoより先にこっちで使い始めてたのですが、諸々あり後発の記事になりました。
そんなわけではじめましょー。
Cloud KMS
暗号鍵をセキュアに管理できるGCPのサービスです。
自動ローテーションやIAMでの権限管理でセキュアなアクセスを実現できる上、APIを利用した暗号化/復号化を行えるので非常に柔軟な利用が可能です。
類似したサービスはAWSの「KMS」や Azureの「Key Vault」などがあります。
Key Ring と Key
Cloud KMS では Key を Key Ring で管理しています。
関係性は字のごとく、鍵と鍵束ですね。
ある程度同じ用途で使用される鍵については同じ Key Ring でまとめておくとよいでしょう。
実際に暗号化などで利用されるのは Key となります。
目的
Cloud KMS に暗号鍵を用意し、Laravel + Cloud KMS で文字列を暗号化/復号化する。
実践
では実際に暗号化/復号化を行いましょう。
大きく分けて作業は3つです。
- 環境準備
- 暗号鍵の準備
- 暗号化
- 復号化
※ 下記手順の[PROJECT_NAME]、[KEY_RING_NAME]、[KEY_NAME] は適宜置き換えてください。
前提条件
前提として下記が導入されていることとします。
なお、バージョンは私の環境でのものです。
- PHP: 7.3.10
- composer: v1.9.0
- Laravel: 6.1
- gcloud: 268.0.0
- terraform: v0.12.16
環境準備
PHPでCloudKMSを扱うためのライブラリをインストールします。
composer でインストールをします。
composer require google/cloud-kms
暗号鍵の準備
暗号をするにはまず暗号鍵を準備しないことには始まりません。
私は terraform を利用しましたが、 gcloud コマンドでも簡単に作成できます。
terraform や gcloud のインストールについては話がそれるので割愛します。
terraform の場合
# 鍵束の作成
resource "google_kms_key_ring" "sample_key_ring" {
name = "[KEY_RING_NAME]"
location = "global"
}
# 鍵の作成
resource "google_kms_crypto_key" "sample_crypto_key" {
name = "[KEY_NAME]"
key_ring = google_kms_key_ring.sample_key_ring.self_link
}
gcloud コマンドの場合
# 鍵束の作成
$ gcloud kms keyrings create [KEY_RING_NAME] --location global --project [PROJECT_NAME]
# 鍵の作成
$ gcloud kms keys create [KEY_NAME] --location global --keyring [KEY_RING_NAME] --purpose encryption --project [PROJECT_NAME]
これで暗号鍵の準備は完了です。
暗号化
では、実際に Laravel で暗号化を行います。
今回は処理を行っている箇所のみ抜粋しています。
use Google\Cloud\Kms\V1\KeyManagementServiceClient;
public function encryption(String $str)
{
$kms = new KeyManagementServiceClient();
$projectId = '<PROJECT_NAME>';
$location = '<PROJECT_LOCATION>';
$keyRingId = '<KEY_RING_NAME>';
$keyId = '<KEY_NAME>';
$cryptoKeyName = $kms->cryptoKeyName($projectId, $location, $keyRingId, $keyId);
return $kms->encrypt($cryptoKeyName, $str)->getCiphertext()
}
これで暗号化した文字列を返すことができます。
なお、Cloud KMS では本気で暗号化されるため、帰ってきた文字列が UTF-8 ではなくなり、
DBなどに直接突っ込むことができません。
DBへ突っ込むときなどは base64_encode を使ってエンコードしておくと良いです。
復号化
暗号化処理はできたので、次に復元しましょう。
やってることはほぼ、暗号化と一緒です。
use Google\Cloud\Kms\V1\KeyManagementServiceClient;
public function decryption(String $str)
{
$kms = new KeyManagementServiceClient();
$projectId = '<PROJECT_NAME>';
$location = '<PROJECT_LOCATION>';
$keyRingId = '<KEY_RING_NAME>';
$keyId = '<KEY_NAME>';
$cryptoKeyName = $kms->cryptoKeyName($projectId, $location, $keyRingId, $keyId);
return $kms->decrypt($cryptoKeyName, $str)->getPlaintext()
}
これで復号化された文字列を取得できます。
なお、暗号化の際に Base64 でエンコードしている場合はデコードしてから渡しましょう
私はこれを忘れてめちゃくちゃ時間食いました。。。
まとめ
前回、Goで行った処理と同様のものをPHPで行いました。
結局やることとしては、暗号化鍵を取得して、それを使って暗号化/復号化をするだけですね。
前の記事でも記載しましたが、今後セキュアでかつ可逆暗号化が必要となるケースがあると思います。
そんなときにぜひこの記事が参考になればと思います。
それでは、みなさまも引き続き安全で快適な暗号化ライフを。