AWS KMS による暗号
概要
AWS Key Management Service (KMS) は、暗号化キーを簡単に作成し、管理するためのサービスです。暗号化キーは設定したポリシーによりアクセスコントロールするだけでなく、その実体は HSM (Hardware Security Module) にて保存され、ハードウェアからも鍵そのものを取り出すことはできないセキュアなものになっています。AWS の各サービスから利用するほか、暗号化ライブラリを使って暗号化処理をおこないます。
AWS KMS で管理するキーはマスターキーであり、「KMS キー」と呼びます(かつては CMK (Customer Master Key) と呼ばれていました)。KMS キーを直接読み取ることはできず、API リクエストにより KMS キーを使った暗号化、復号をおこないます。1 回のリクエストで暗号化できるのは 4KB までと小さく、また同じ暗号キーを使って大量のデータを暗号化し続けると暗号化キーを解析されるリスクも高まるため、通常はデータ自体を暗号化するためのデータキーを動的に生成し、そのデータキーを KMS キーで暗号化して一緒に保存する「エンベロープ暗号」という手法を用います。この場合、KMS キーはラップキー(またはキー暗号化キー)の位置づけになります。
KMS キーの種類
参考) AWS KMS keys
KMS キーには以下の種類があり、それぞれの特徴があります。
- AWS owned key (AWS 所有のキー)
- AWS アカウント外で AWS により管理されている KMS キー
- 設定の変更、参照、キーの削除は不可
- AWS managed key
- 各 AWS サービスが AWS アカウント内に自動的に生成する KMS キー
- 設定の変更、キーの削除は不可
- Customer managed key
- ユーザーが自分で作成、管理する KMS キー
- 用途に応じてアクセス範囲を制限するポリシーを設定可能
- 外部から暗号キーを取り込んで利用することもできる
キーのローテーション
特定の暗号キーで大量のデータを暗号化すると、キーを解析されるリスクが高まるため、定期的に暗号キーを更新することが推奨されます。
生成した KMS キーに紐付く暗号キー(外部から取り込んだ暗号キーを除く)は、自動で定期更新することができます。その場合、KMS キー内部で古い暗号キーも引き続き保持され、更新前の暗号キーで暗号化されたデータも復号することができます。ローテーション間隔は 1 年固定となっており、変更はできません。
キーを 1 年ではなく任意のタイミングで手動更新したい場合は、新しい KMS キーを作成して切り替える必要があります。エイリアス機能を使用すれば利用者の設定を変更する必要はなくなりますが、古い暗号キーで暗号化したデータの復号には更新前の KMS キーを指定する必要があります。
キーの種類 | ローテーション |
---|---|
AWS owned key | 常に有効 (間隔はサービスによって異なる) |
AWS managed key | 常に有効 (1 年ごと) |
Customer managed key (Symmetric) | 設定可 (無効、または 1 年ごと) |
Customer managed key (その他) | 無効 |
使用例
KMS キーでデータ直接を暗号化する方法です。
KMS キーによる暗号化
kms:Encrypt API を使用して暗号化します。
$ aws kms encrypt --key-id "(KMS キー ID)" --plaintext "(平文データ)"
{
"CiphertextBlob": "(暗号化されたデータの Base64)",
"KeyId": "(KMS キーの ARN)",
"EncryptionAlgorithm": "SYMMETRIC_DEFAULT"
}
kms:Decrypt API を使用して復号します。
$ aws kms decrypt --key-id "(KMS キー ID)" --ciphertext-blob "(暗号化されたデータの Base64)"
{
"KeyId": "(KMS キーの ARN)",
"Plaintext": "(平文データ)",
"EncryptionAlgorithm": "SYMMETRIC_DEFAULT"
}
エンベロープ暗号
kms:GenerateDataKey API を使用してデータキーを生成すると、データキーと、KMS キーにより暗号化されたデータキーの両方が取得できます。暗号化処理が終わったらプレーンなデータキーはすぐに破棄し、暗号化されたデータキーを保存しておきます。
$ aws kms generate-data-key --key-id alias/test --key-spec AES_256 | tee key.json
{
"CiphertextBlob": "(暗号化されたデータキーの Base64)",
"Plaintext": "(データキーの Base64)",
"KeyId": "(KMS キーの ARN)"
}
$ DATA_KEY=$(jq -r '.Plaintext' key.json | base64 -d | xxd -p -c 32)
$ openssl enc -aes256 -K "${DATA_KEY}" -iv 0 -in plaintext.txt -out encrypted.dat
kms:Decrypt API を使用してデータキーを復号し、データキーを使ってデータを復号します。
$ aws kms decrypt --key-id "(KMS キー ID)" --ciphertext-blob "(暗号化されたデータキー)" | tee key.json
{
"KeyId": "(KMS キーの ARN)",
"Plaintext": "(データキー)",
"EncryptionAlgorithm": "SYMMETRIC_DEFAULT"
}
$ DATA_KEY=$(jq -r '.Plaintext' key.json | base64 -d | xxd -p -c 32)
$ openssl enc -d -aes256 -K "${DATA_KEY}" -iv 0 -in encrypted.dat