AWS KMSのデータキーとエンベロープ暗号化
AWS KMSのGenerateDataKeyで生成するデータキーの役割、エンベロープ暗号化によるアプリケーションデータの暗号化・復号、平文キーと暗号化済みキーの安全な扱いをDVA向けに詳しく解説します。
AWS KMSのデータキーとエンベロープ暗号化
アプリケーションがファイルやデータベースのレコードを暗号化するとき、AWS Key Management Service(AWS KMS)のキーでデータ全体を直接暗号化するのではなく、データキー(data key)でデータ本体を暗号化し、そのデータキーをKMSキーで保護する方法がよく使われます。この方式をエンベロープ暗号化と呼びます。
このページでは、KMSキーとデータキーの役割の違い、データキーを生成してアプリケーションデータを暗号化する手順、暗号化済みデータキーをデータと一緒に保存する理由、後からの復号方法を順に確認します。
KMSキーとデータキーの役割
KMSキーは、暗号化キーを保護し、誰が暗号処理を要求できるかを管理するAWS KMS内の論理的なキーです。KMSキーに関連するキーマテリアルそのものをアプリケーションへダウンロードすることはできません。許可されたアプリケーションはKMS APIを通じて、そのキーを使った操作を依頼します。
一方、データキーは、アプリケーションが管理するデータを実際に暗号化・復号するために使う対称キーです。データキーはKMSキーとは別に生成されます。アプリケーションは平文のデータキーを一時的に受け取り、KMSの外でローカルな暗号ライブラリなどを使ってデータを処理できます。
| キー | 主な役割 | アプリケーションからの扱い |
|---|---|---|
| KMSキー | データキーを暗号化し、必要なときに復号する。使用権限を制御・監査する | キーマテリアルを直接取得せず、KMS APIで操作を要求する |
| 平文データキー | アプリケーションデータを実際に暗号化・復号する | 必要な処理の間だけメモリ上で扱い、処理後に消去する |
| 暗号化済みデータキー | 平文データキーを保護された形で保持し、後日の復号に使う | 暗号化データと一緒に保存できる。復号時にKMSへ渡す |
データキーは暗号化の都度、新しく生成する形が望ましい設計です。KMSはGenerateDataKeyの要求に対しデータキーを生成しますが、データキーを保管・追跡・管理するサービスではありません。生成されたデータキーの平文を保持するか、暗号化済みコピーをどこへ保存するかは、アプリケーション側で適切に扱う必要があります。
エンベロープ暗号化を使う理由
大量のデータをKMS APIへ直接送って暗号化するのではなく、アプリケーション側でデータキーを使って暗号化すれば、データ本体をKMSの暗号APIへ送らずに処理できます。データサイズに応じたローカル暗号ライブラリを利用でき、データ全体について暗号APIを呼び出す設計を避けられます。
KMSのEncrypt APIで対称暗号化キーが直接暗号化できる平文は最大4,096バイトです。これはKMS Encrypt APIの入力上限であり、AWSのすべての暗号化機能のデータサイズ上限を意味するわけではありません。大きなオブジェクトや大量のアプリケーションデータでは、KMSのGenerateDataKeyを使ってデータキーを得て、データ本体をクライアント側で暗号化する方法が適しています。
また、KMS APIリクエストの回数に応じた料金が発生する場合があります。データ全体の暗号化のために個々のチャンクごとにKMSを呼び出すのではなく、データキーを用いたローカル処理と、必要なデータキー生成・復号の呼び出しを組み合わせることで、処理性能とAPI利用回数を考慮した設計にできます。料金はキーの種類や利用状況で異なるため、実際の料金表を確認します。
GenerateDataKeyでデータキーを取得する
アプリケーションはAWS SDKなどを介してAWS KMSのGenerateDataKey APIを呼び出します。リクエストには、データキーを保護するKMSキーの識別子が必要です。呼び出し元には対象キーのkms:GenerateDataKeyを許可し、キーの状態やキーポリシーなども操作可能な状態にしておきます。
GenerateDataKeyではデータキーの種類を指定します。一般的な例はAES_256またはAES_128です。要求するKMSキーは対称暗号化KMSキーでなければなりません。GenerateDataKeyの応答には、次の2種類の同じデータキーが含まれます。
- 平文のデータキー(
Plaintext):アプリケーションがデータ本体の暗号化に使う。 - 暗号化済みデータキー(
CiphertextBlob):指定したKMSキーで暗号化された、平文データキーのコピー。後で復号するときに使う。
KMSはこのデータキーを、指定された対称暗号化KMSキーの下で暗号化します。アプリケーションが受け取る平文のデータキーはKMSキーのキーマテリアルではなく、アプリケーション自身が使う別の一時的なキーです。
アプリケーションデータを暗号化して保存する
たとえば、温室のセンサー群から届く温度・湿度の計測記録を、一定期間ごとのアーカイブとして保存するサービスを考えます。記録の量が大きくなっても、KMSへ計測データ全体を送る必要はありません。
-
アプリケーションがKMSキーを指定してデータキーを要求する
アプリケーションはGenerateDataKeyを呼び出し、対象のカスタマー管理KMSキーなどのキー識別子と、AES_256などのデータキー仕様を指定します。必要な権限がない場合、KMSは要求を拒否します。 -
KMSがデータキーを生成して2種類のコピーを返す
AWS KMSがデータキーを生成し、指定されたKMSキーを使って暗号化します。レスポンスには、直ちに使う平文コピーと、後日の復号に使う暗号化済みコピーの両方が含まれます。KMSはこのデータキーを永続保存しません。 -
アプリケーションが平文データキーでデータを暗号化する
アプリケーションはAWS KMSの外部で、平文データキーと暗号ライブラリを用いてセンサー記録を暗号化します。実際の方式では、データの機密性だけでなく改ざん検出も必要かを考慮し、認証付き暗号など適切な方式を選びます。nonceや初期化ベクトル、認証タグなど復号に必要な値が生じる方式では、それらもデータとともに保存します。 -
使い終えた平文データキーを消去する
暗号化が終わったら、平文データキーをメモリからできるだけ早く消去します。平文キーをデータベースやファイルへ保存したり、ログ、トレース、エラーメッセージに含めたりしてはいけません。プログラミング言語やランタイムによって完全なメモリ消去の保証は異なるため、キーを扱う範囲と保持時間をできるだけ小さくします。 -
暗号化データと暗号化済みデータキーを一緒に保存する
暗号文だけでなく、その暗号文に対応する暗号化済みデータキーも保存します。これにより、KMSに平文キーを保管させず、後の復号に必要なキー情報を暗号文に結び付けて保持できます。データベースやオブジェクトストレージなどでは、暗号化済みキー、KMSキーの参照情報、暗号化コンテキスト、暗号アルゴリズムに必要なメタデータを、対象データと対応づけて記録します。
暗号化済みデータキーは、KMSキーそのものでも平文のデータキーでもありません。適切なKMSキーと必要な許可なしに、その値だけから元のデータキーを取り出すことはできません。データごとにデータキーを生成し暗号化済みキーをそのデータと保存すれば、KMSキーをアプリケーションに開示せず、キーの保護とデータ本体の暗号化を分担できます。
後からデータを復号する
保存したセンサー記録を読み出すときは、対応する暗号化済みデータキーを使って、まずKMSから一時的な平文データキーを取得します。その平文キーでアプリケーション側の暗号文を復号し、処理後に平文キーを消去します。
- アプリケーションが暗号文に対応する暗号化済みデータキーを読み出す。
- そのキーを
DecryptAPIに渡す。暗号化時に暗号化コンテキストを指定した場合は、同じコンテキストを指定する。 - AWS KMSが適切なKMSキーを使ってデータキーを復号し、平文データキーをアプリケーションに返す。
- アプリケーションがローカルで暗号文を復号し、平文データキーをできるだけ早くメモリから消去する。
暗号化済みデータキーは、暗号化対象データと切り離さずに関連づけて保管します。どの暗号化済みキーがどの暗号文に対応するか分からなくなると、正しいデータキーを使えません。また、復号にはKMSキーの利用許可と、そのキー自体が利用可能な状態であることが必要です。キーを無効化・削除したり、必要な権限を取り消したりすると、暗号化済みデータキーを復号できず、結果として対象データも復号できなくなる可能性があります。
暗号化コンテキストを利用する場合
対称暗号化KMSキーでGenerateDataKeyを使うとき、必要に応じて**暗号化コンテキスト(encryption context)**を指定できます。暗号化コンテキストは暗号化操作に関連付ける追加の認証情報で、機密情報ではないキーと値の組です。監査情報として有用な一方、CloudTrailなどに記録される可能性があるため、個人情報や秘密値を含めてはいけません。
暗号化コンテキストを指定してデータキーを生成した場合、その暗号化済みデータキーをDecryptするときには、同じコンテキストを同じ大文字・小文字で指定します。値が一致しない、または復号時に指定しない場合、復号は失敗します。アプリケーションが暗号化済みデータキーとともに保存するメタデータを設計するときは、後から同一のコンテキストを確実に復元できるようにします。
安全なキー管理の要点
- 平文キーを永続化しない:平文データキーを保存するのではなく、KMSが返す暗号化済みコピーを暗号文に添付する。
- 処理後に平文キーを消去する:メモリ上での保持時間と、ログ・例外・デバッグ出力などへの漏えい経路を抑える。
- KMSキーとデータキーを混同しない:アプリケーションが使うのは一時的なデータキーであり、KMSキーのキーマテリアルはKMSの保護境界から持ち出さない。
- キーのアクセス許可を絞る:データキーを要求する処理に、対象キーに対する
kms:GenerateDataKeyだけでなく、用途に応じて復号側のkms:Decryptなど必要な操作だけを与える。キーポリシーやIAMの設定も確認する。 - 復号に必要な情報をデータと管理する:暗号化済みデータキー、キーの参照情報、暗号化コンテキスト、暗号方式のメタデータを暗号文に結び付ける。
- 同じデータキーを使い回すなら方式の要件を守る:データキーを複数の暗号化に使う設計では、暗号方式が定めるnonceなどの一意性要件を満たす。個別データごとに新しいデータキーを生成する方法は、使い回しを避ける設計の一つである。
- 暗号化以外の制御も維持する:暗号化はデータへの認可、ネットワーク保護、監査、バックアップを置き換えない。アプリケーションが復号できる主体やデータストアへのアクセスも別に制御する。
DVA試験での判断ポイント
- 大きなアプリケーションデータを暗号化する要件では、データ全体をKMS
Encryptへ渡すのではなく、GenerateDataKeyでデータキーを得てアプリケーション側で暗号化するパターンを選ぶ。 GenerateDataKeyは同じデータキーの平文コピーと、指定した対称暗号化KMSキーで暗号化したコピーを返す。平文コピーはデータ暗号化に、暗号化済みコピーは後日の復号に使う。- KMSはデータキーを永続保存せず、データ本体をデータキーで暗号化する処理も実行しない。平文データキーの扱いとローカル暗号処理はアプリケーションの責任である。
- 平文データキーは暗号化・復号処理の間だけメモリに置き、処理後に消去する。暗号化済みデータキーを暗号文と一緒に保存し、平文キーを保存しない。
- 後日の復号では、保存した暗号化済みデータキーをKMS
Decryptへ渡して平文データキーを得てから、アプリケーション側で暗号文を復号する。 GenerateDataKeyにはKMSキーの指定と適切なkms:GenerateDataKey許可が必要である。暗号化コンテキストを使った場合は、復号時に完全に一致するコンテキストが必要になる。- KMS
EncryptAPIの対称キーでの入力上限は4,096バイトである。これはKMSEncryptAPIの制限であり、データキーを使ったローカル暗号化が必要となる代表的な理由の一つ。
AWS公式ドキュメント
重要ポイント
- ▸データキーはアプリケーションデータを実際に暗号化・復号する対称キーであり、KMSキーとは別の一時的なキーである
- ▸GenerateDataKeyは指定した対称暗号化KMSキーの下で、平文データキーと暗号化済みデータキーを返す。KMSはデータキーを永続保存しない
- ▸大きなデータ本体はアプリケーション側でデータキーを使って暗号化する。KMS Encrypt APIは対称キーで最大4,096バイトの平文しか直接暗号化できない
- ▸平文データキーは暗号化処理の間だけメモリ上で扱い、使用後できるだけ早く消去する。永続化・ログ出力してはいけない
- ▸後で復号できるように、暗号化済みデータキーを暗号文と一緒に保存し、復号時にKMSのDecryptへ渡して一時的な平文データキーを得る
- ▸データキー生成時にはKMSキーを指定し、呼び出し元にkms:GenerateDataKeyを許可する。暗号化コンテキストを使う場合は復号時に同一の値を指定する
このトピックの学習を完了しますか?
完了状態はいつでも切り替えられます
この試験ドメイン内で次の学習に進む
同じサービスの関連トピック
KMS と暗号化 に関連するトピックを続けて確認できます。