4
2

More than 3 years have passed since last update.

Laravel で Cloud KMS を使って暗号化/復号化をしてみた。

Posted at

こんにちわ! @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で行いました。
結局やることとしては、暗号化鍵を取得して、それを使って暗号化/復号化をするだけですね。
前の記事でも記載しましたが、今後セキュアでかつ可逆暗号化が必要となるケースがあると思います。
そんなときにぜひこの記事が参考になればと思います。
それでは、みなさまも引き続き安全で快適な暗号化ライフを。

4
2
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
4
2