KMSの概念
KMSは、FIPS 140-3 検証済みのハードウェアセキュリティモジュール(HSM)を利用して暗号鍵を生成・保護する。KMS HSM は、セキュリティとスケーラビリティの要件を満たす専用の暗号化機能を提供するように設計された マルチチップスタンドアロンなハードウェア暗号化アプライアンス である。
マスターキーとデータキー
S3 に格納するデータはデータキー(CDK: Customer Data Key)を用いて暗号化する。CDK はマスターキー(CMK、現在の用語では KMS キー)によって暗号化される。CMK のキーマテリアルは AWS 管理の HSM 外では常に暗号化された状態で保持され、この「マスターキーでデータキーを暗号化し、そのデータキーでオブジェクトを暗号化する」フローをエンベロープ暗号化と呼ぶ。
- マスターキー
- 三種類存在。AWSマネージド型、カスタマー管理型、AWS所有型1
- AWS所有型は、ユーザーからは見えない
- AWSマネージド型は、キーのエイリアス名が
alias/aws/{service名}になる(例:alias/aws/s3) - カスタマー管理型は、キーローテーション、ポリシーによるアクセス制御、エイリアスの作成などができる
- ドメインキーによって暗号化される
- 三種類存在。AWSマネージド型、カスタマー管理型、AWS所有型1
- データキー2
- アクション
GenerateDataKeyによって生成される - ユーザーが暗号化するオブジェクト自体は、データキーによって暗号化される
- アクション
ドメインキーについて 3
HSMメモリ上にのみ存在する(ユーザーからは見えない)、256-bit AES-GCMキー。KMS key(マスターキー、HBK)をラップして暗号化するのに使用されている。
{DK_r} という集合として管理されている。常に 1 つのアクティブなドメインキーと、複数の非アクティブなドメインキー(過去のドメインキー)を保持している。
キーマテリアル
CMKのメタデータを除く、暗号・復号に利用する部分のことを キーマテリアル 4 と呼ぶ = キー本体
- キーマテリアルが BYOK(Bring Your Own Key)できる
- 「CMK がインポート可能」というより、CMK のキーマテリアル(対称鍵)だけをインポートする イメージ
- インポート可能なのは 256 bit の対称キー(AES-256)に限定される
- インポートしたキーマテリアルには有効期限(Expiration)を設定でき、期限到来時に自動削除させることもできる
- 自動ローテーションは使えないが、新しいキーマテリアルを再インポートする/別の KMS キーに切り替える といった運用で手動ローテーションが可能
暗号化アルゴリズム
- 対称鍵暗号
- KMS の「対称 KMS キー」(
KeySpec = SYMMETRIC_DEFAULT)で利用される。内部的には AES-256-GCM ベースのアルゴリズムが使われる。
- KMS の「対称 KMS キー」(
- 非対称鍵暗号
- RSA(
RSA_2048/RSA_3072/RSA_4096)や楕円曲線暗号(ECC_NIST_P256など)を用いた暗号化・署名・検証に対応する。
- RSA(
- MAC / HMAC
-
HMAC_256などの MAC 専用キーを使い、メッセージ認証コード(MAC)の生成・検証を行う。
-
KMSのアクセス制御
アクセス制御の種類
- キーポリシー
- IAMポリシー
- グラント
ポリシーによる制御
-
同一アカウント内の場合
KMSキーとIAMプリンシパルが同じAWSアカウントにある場合、キーポリシーだけで完結させることもできるし、キーポリシーでアカウント(root)に委譲して IAM ポリシーで細かく制御する こともできる。 -
異なるアカウントを跨ぐ場合
一方で、別アカウントのキーにアクセスする場合には、キーポリシーのみでアクセスを許可することはできない。- キー所有側アカウントのキーポリシーで、呼び出し元アカウント/ロールにアクセスを許可し
- かつ呼び出し元アカウントの IAM ポリシーで、そのロールに対して KMS API 呼び出し権限を付与する
という 両方の条件 を満たす必要がある。
IAM ポリシーを使用して KMS キーへのアクセスを制御するには、まずキーポリシー側で「このアカウントの IAM ポリシーによるアクセス許可を有効にする」(典型的には Principal: {"AWS": "arn:aws:iam::<AccountId>:root"})必要がある。
= IAMポリシー単体ではアクセスは成立せず、必ずキーポリシーとセットで評価される。
グラントによる制御
IAMプリンシパルに対して、特定の KMS キーに関する限定的かつ(必要に応じて)時間制限付きのアクセス権を付与する仕組み。
グラント対象のプリンシパルは別アカウントであっても同一アカウントにあっても良い。
CreateGrant を呼ぶとグラントが作成され、オプションで グラントトークン(GrantTokens) が返される。作成直後の短い間に限り、このトークンをリクエストに付加することで、まだ整合していないグラントを即座に有効として扱うことができる(グラントトークンは認証情報ではなく、「この新しいグラントを今すぐ反映してほしい」というヒント)。
KMSのキーローテーション
- KMS のキーローテーション5は、keyマテリアルを新しく生成するプロセスで、古いkeyマテリアルは削除しない。同じ KMS キー ID のまま新しいキーマテリアル(HBK のバージョン)を生成して current とマークするイメージであり、エイリアスが指す KeyId は変わらない。
- バージョンは複数持てるので、古くなったキーマテリアルで暗号化されているCDKも復号できる。復号時には CiphertextBlob に含まれる情報からどのバージョンで暗号化されたかが特定され、対応するキーマテリアルが自動的に使われる。

※ https://docs.aws.amazon.com/ja_jp/kms/latest/developerguide/rotate-keys.html
ドメインキーのローテーション
以下のセキュリティの推奨事項を満たすように、原則1日ごとにローテーションされる。ローテーション時には、古いドメインキーですべてのHBK を復号して再度新しいドメインキーで暗号化する。
KMSのアクション
Encrypt
アクション概要
KeyId / Alias + 平文 + Encryption Context を送ると、4 KB 以下の平文データを直接暗号化する。
KMS は対象 KMS キーに対応する current な EKT(暗号化されたキーマテリアル)を取得し、HSM 内で HBK に復号したうえで暗号化処理を行い、ciphertext(CiphertextBlob)を返却する。
ユースケース / 対応する要件
- 小さいデータを暗号化するときにのみ利用する(ユーザー目線ではあまり使わない)。
- 暗号化アクションが付属しているデータ保存アクションで、内部的に
Encryptが呼ばれることもあるので、どの API を使うか次第で必要になる
備考
- KMS 側は平文も暗号文も保存しない
GenerateDataKey
アクション概要
KeyId / Alias を送ると、KMS は指定された KMS key の current HBK を利用してランダムな Data Key を生成する。
その結果として、以下を返却する。
- 平文の Data Key
- HBK で暗号化した暗号化 Data Key(CiphertextBlob)
- どの KMS キーで暗号化したかを示すキー ID
呼び出し元は、平文の Data Key でオブジェクトを暗号化したあと、平文の Data Key をメモリから削除し、暗号化された Data Key(CiphertextBlob)のみを永続化する。
CiphertextBlob は KMS 独自フォーマットの暗号文で、どの HBK で暗号化されたかを示すメタ情報を含む。
ユースケース / 対応する要件
- 4 KB 以上のデータの暗号化時に利用する
- S3 に配置するオブジェクトの暗号化には基本的にこれを利用する(エンベロープ暗号化)
備考
- エンベロープ暗号化の “データキー生成+ラップ” を担うアクション
Decrypt
アクション概要
CiphertextBlob 内部の追加情報(ヘッダ)から、どの KMS キー/HBK で暗号化されたかを特定する。
暗号文の構造からノンス等を抽出し、その HBK で暗号化されたデータ(またはデータキー)を復号し、平文 Data Key や平文データを KMS ホスト経由でクライアントに返却する。
ユースケース / 対応する要件
- 暗号化されたオブジェクトや、暗号化 Data Key を復号するときに使う
- エンベロープ暗号化の場合は、まず
Decryptで平文 Data Key を取得し、その Data Key でオブジェクト本体を復号する
備考
- 復号に使用する HBK のバージョンは CiphertextBlob のメタデータから自動的に特定される。
- 通常、
Decrypt呼び出し時にKeyIdを明示する必要はない(Ciphertext 側にキー情報が埋め込まれているため)
ReEncrypt
アクション概要
CiphertextBlob, DestinationKeyId を渡すことで、新しい鍵で再暗号化される。
CiphertextBlob には暗号化されたデータと、暗号化に使われた鍵の情報が含まれているため、それを使って KMS 内部で一度復号したあと、指定した別の KMS キーで再暗号化する。
ユースケース / 対応する要件
- 「常に最新の鍵で暗号化されていなければいけない」といった要件がある場合
- 別アカウントや別リージョンの KMS キーに暗号化を移行したい場合
- アプリケーション側で平文を扱わずに、暗号化状態のまま暗号鍵だけを切り替えたいケース
備考
- 再暗号化の過程で平文は KMS 内部の HSM から外に出ないため、アプリ側は常に CiphertextBlob だけを扱える
- セキュリティ要件が厳しい環境での「鍵ローテーションの追従」や「鍵の移管」に適している
CreateGrant
アクション概要
KMS キーに Grant を追加する。
Grant はキー ポリシーや IAM ポリシーとは独立したレイヤとして評価され、これらのポリシーに「このプリンシパルにはこの操作だけを許可する」といった一時的/限定的な許可を上乗せするために使える。
ユースケース / 対応する要件
- 一時的な復号許可などの KMS キーアクセスを特定のプリンシパルに与えたいとき
- アプリケーションや別アカウントのロールに対して、限定スコープの権限を安全に委譲したいとき
- それ以外の一般的なケースでは、基本的にポリシーベース(キーポリシー+IAMポリシー)で許可する
備考
-
CreateGrantによる権限の操作が KMS 全体で完全に有効になるまでに、最大数分程度のラグがある - その間にすぐ反映させたい場合は、レスポンスで返される
GrantTokensを後続リクエストに付与して即時反映させる - Grant は「権限の“差分”を別オブジェクトとして管理する」仕組みであり、ポリシーを変更せずにきめ細かい委譲ができる
Encryptの図解
※ 暗号化情報: 復号するのに必要な、暗号化に利用した鍵やアルゴリズム、付随メタデータに関する情報。典型的には CiphertextBlob や KeyMaterialId、Encryption Context などを指す。
Decryptの図解
以下に、S3から暗号化されたファイルをダウンロードするときの復号化フローを示す。
蛇足
CloudHSM vs KMS
多くのユースケースでは、AWS KMS が提供するマネージドな KMS キー(AWS 管理の HSM 上のキー)で暗号化するだけで十分です。
一方で、コンプライアンスや社内セキュリティポリシーによって、
- 「マスターキーを自社(カスタマー)管理の HSM 上で生成・保持しなければならない」
- 「クラウド事業者側のオペレータからもキーに手が届かない構成が必須」
といった、より強い要件が課されるケースがあります。この場合、AWS が管理する HSM 上でキーマテリアルを保持する通常の KMS キーだけでは要件を満たせません。
このような状況で選択肢になるのが AWS CloudHSM です。
CloudHSM は「HSM で鍵を生成するだけのサービス」ではなく、PKCS#11 や JCE、OpenSSL エンジンなどを通じて、HSM 上での鍵生成・暗号化・復号・署名といった暗号処理をアプリケーションから直接実行することができます。
さらに、KMS と連携して CloudHSM を KMS のカスタムキーストアとして使う 構成を取れば、「マスターキーは自社管理 HSM に置きつつ、KMS の API や他 AWS サービスとの統合性をそのまま活用する」といった設計も可能です。
-
https://docs.aws.amazon.com/ja_jp/kms/latest/developerguide/data-keys.html ↩
-
https://docs.aws.amazon.com/ja_jp/kms/latest/cryptographic-details/domains-and-domain-state.html ↩
-
https://qiita.com/aminosan000/items/43c8b63dd02aa0552657#%E3%82%AD%E3%83%BC%E3%83%9E%E3%83%86%E3%83%AA%E3%82%A2%E3%83%AB%E3%81%AE%E3%82%A4%E3%83%B3%E3%83%9D%E3%83%BC%E3%83%88 ↩
-
https://docs.aws.amazon.com/ja_jp/kms/latest/developerguide/rotate-keys.html ↩

