AWS KMSのエンベロープ暗号化を理解する

AWS Certified Security - Specialty の学習の一貫で KMS について勉強していた。 Black Belt を観て CLI を叩いたりしていて、GenerateDataKey APIユースケースが思い浮かばなかったので整理する。

前提

  • 対称暗号化 KMS キー(SYMMETRIC_DEFAULT)

処理の流れを整理

通常の Encrypt / Decrypt を利用した場合と、エンベロープ暗号化を利用した場合の流れを整理する。

Encrypt / Decrypt

特に手元に鍵を用意することなく、カジュアルに利用することが可能。 AWS CLI で Encrypt API を呼び出す際は、渡す平文(--plaintext)を事前に base64 エンコードしておく必要がある。 Decrypt API を呼び出す際は、返却された平文(Plaintext)を base64 デコードしてあげる。

  1. Encrypt API で CMK を利用しての平文を暗号化
  2. Decrypt API で CMK を利用して暗号データを復号

エンベロープ暗号化

Encrypt / Decrypt と比較すると手順が多い。暗号化と復号それぞれで手順をみていく。

暗号化

  1. GenerateDataKey API で CMK を利用して CDK を作成
    • データキーと暗号化されたデータキーを返す
  2. データキーを利用して任意の平文を暗号化
    • データキーはメモリ上に保持する
  3. 暗号化されたデータキーをディスクなどに保存
  4. データキーを削除

復号

  1. Decrypt API で CMK を利用して暗号化されたデータキーを復号
    • "暗号化"の 4 で保存したデータキーを送信
  2. 1 で返却されたデータキーを利用して暗号化されたデータを復号
    • データキーはメモリ上に保持する
  3. データキーを削除

Encrypt / Decrypt とエンベロープ暗号化の比較

簡単にまとめてみる。

Encrypt / Decrypt エンベロープ暗号化 備考
データ上限 4 KB なし
API 呼び出し頻度 多い 少ない
実装の容易さ △(※) ※ Encryption SDK 利用推奨
データキーの発行有無 なし あり
意図せず CMK が無効化もしくは削除された場合の影響

データ上限については分かりやすくて、4 KB 以上のデータを暗号化する必要がある場合はエンベロープ暗号化を利用せざるを得ない。API の呼び出し頻度については、Ecrypt / Decrypt の場合は都度呼び出す必要があるが、エンベロープ暗号化の場合は暗号化の処理を言語のライブラリ(Python だと cryptography など)で実装することができて、スロットリングが発生する可能性も低い。実装の容易さは Encrypt / Decrypt に軍配が上がるが、AWS から Encryption SDK というエンベロープ暗号化を簡単に実現できるライブラリが提供されている。Encryption SDK を利用することで、簡単に、かつ耐障害性のあるアプリケーションの実装が可能となる。

docs.aws.amazon.com

意図せず CMK が無効化もしくは削除された場合の影響について、CMK の場合はどうしようもないが、エンベロープ暗号化の場合はどうにかなる。仮に CMK が削除された場合、既にデータキーを発行している状態であれば引き続き暗号化は可能である。復号する場合どうすればいいのかはまだ理解できていないが、KMS のベストプラクティス(PDF)には DR の設計にも有用との記載があった。

どちらの方法を選択するにせよ、セキュアであることに変わりはなさそう。CMK の保守性であったり、可用性を高める場合はエンベローブ暗号化を使ったほうがよさそう。暗号化されたデータキーをどこに保持しておくかは検討する必要がありそう。どこにおいたほうがベストかはまだ分かっていないが、Encryption SDK では暗号化されたデータキーをキャッシングする機構もあるようだ。

ユースケース

雑に書くと、以下の条件に当てはまる場合はエンベロープ暗号化を利用したほうがよさそう。

  • 4 KB 以上のデータを暗号化する必要がある
  • バックエンドの Web API などで、多くのリクエストが見込まれる
    • 毎リクエストで暗号化する必要がある前提
  • 高可用性が求められる

具体的なユースケースは思い浮かばなかったが(ごめんなさい)、EC2 の EBS 暗号化でも、実際にエンベロープ暗号化を利用しているそう。高可用性が求められるサービスのため、エンベロープ暗号化を利用する必要があったといえる。

サンプルコード

実際にエンベロープ暗号化を実装したら理解が進んだ。合っているかどうか怪しいので参考までに。

github.com

参考

docs.aws.amazon.com

aws.amazon.com

docs.aws.amazon.com

qiita.com

stackoverflow.com

おわりに

GenerateDataKey API はどのようなユースケースで使うのだろうか。という疑問から、実際に実装しながら、ドキュメントを読みつつ理解を深められた。調べれば調べるほど KMS は奥が深くて、他の AWS サービスとも連携していて面白いなと感じた。KMS 完全に理解した。

今回は学習のため Encryption SDK は利用しなかったが、こんど実際に使ってみて便利さに驚愕したい。おそらくとても便利。