お勉強のためにCLIでKMSを使った暗号化を試してみたメモ。
処理の流れ
データの暗号化は以下の流れで実施する。
- KMSでマスターキーを作成する(CreateKey)
- データキー作成APIを叩く(GenerateDataKey)
- 平文データキーとマスターキーで暗号化されたデータキーが返ってくる
- 平文データキーで暗号化したいデータを暗号化する
- 平文データキーを削除する
- 暗号化されたデータ暗号化されたデータキーを同じ場所で保存する
データの復号は以下の流れで実施する。
- 復号APIを叩く
- 平文データキーが返ってくる
- 平文データキーで暗号化されたデータを復号する
- 平文データキーを削除する
CLIで実施
CLIでデータの暗号化操作を試す。
カスタマーキーの作成
マスターキーを作成し、エイリアスをつけておく。
master_key_arn=$(aws kms create-key --query KeyMetadata.Arn --output text) master_key_id=${master_key_arn##*/} aws kms create-alias \ --alias-name alias/sample-master-key \ --target-key-id ${master_key_id}
キーとキーポリシーを確認する。
$ aws kms describe-key --key-id ${master_key_id} { "KeyMetadata": { "AWSAccountId": "XXXXXXXXXXXX", "KeyId": "e6e603eb-e463-432b-806e-aa64a8f191cc", "Arn": "arn:aws:kms:ap-northeast-1:XXXXXXXXXXXX:key/e6e603eb-e463-432b-806e-aa64a8f191cc", "CreationDate": "2020-05-01T13:00:28.388000+09:00", "Enabled": true, "Description": "", "KeyUsage": "ENCRYPT_DECRYPT", "KeyState": "Enabled", "Origin": "AWS_KMS", "KeyManager": "CUSTOMER", "CustomerMasterKeySpec": "SYMMETRIC_DEFAULT", "EncryptionAlgorithms": [ "SYMMETRIC_DEFAULT" ] } } $ aws kms get-key-policy --key-id ${master_key_id} --policy-name default { "Policy": "{\n \"Version\" : \"2012-10-17\",\n \"Id\" : \"key-default-1\",\n \"Statement\" : [ {\n \"Sid\" : \"Enable IAM User Permissions\",\n \"Effect\" : \"Allow\",\n \"Principal\" : {\n \"AWS\" : \"arn:aws:iam::XXXXXXXXXXXX:root\"\n },\n \"Action\" : \"kms:*\",\n \"Resource\" : \"*\"\n } ]\n}" } $ aws kms get-key-policy --key-id ${master_key_id} --policy-name default | jq -r '.Policy' | jq . { "Version": "2012-10-17", "Id": "key-default-1", "Statement": [ { "Sid": "Enable IAM User Permissions", "Effect": "Allow", "Principal": { "AWS": "arn:aws:iam::XXXXXXXXXXXX:root" }, "Action": "kms:*", "Resource": "*" } ] }
キーポリシーではIAMユーザー全体が許可されているので、IAMユーザーに権限があればキーにアクセスできる。今回は管理者権限のあるユーザーで操作しているのでアクセスできる。
データの暗号化
暗号化したいデータを用意する。
cat <<EOF > plaintext-data.txt Hello World! EOF
マスターキーを指定し、データキーを作成する。
aws kms generate-data-key \ --key-id ${master_key_id} \ --key-spec AES_256 > generate-data-key-response.json
レスポンスの内容を確認する。Plaintextが平文データキーで、CiphertextBlobがマスターキーで暗号化されたデータキー。
$ cat generate-data-key-response.json { "CiphertextBlob": "AQIDAHgX8Ezyy+LslKPEZFBMzquXkfEIBf5KiG30hr6DrYByPAF1OOxZnAQCsaf7Ke1fWe7EAAAAfjB8BgkqhkiG9w0BBwagbzBtAgEAMGgGCSqGSIb3DQEHATAeBglghkgBZQMEAS4wEQQMldmNdV+smKOHHupHAgEQgDvUJVao4FbT7ewFcHgGaCnisntNYMsDpCrony+xs1qVmwQphiiazFZvi1L0WqHMPmyYW1RopFT/HMHOkQ==", "Plaintext": "sbK7LuWiBjV8LR76MDNLMQIpFfh6xITEG6GOcaYdQEU=", "KeyId": "arn:aws:kms:ap-northeast-1:XXXXXXXXXXXX:key/e6e603eb-e463-432b-806e-aa64a8f191cc" }
PlaintextとCiphertextBlobをBase64でデコードしてファイルに保存しておく。
cat generate-data-key-response.json | jq -r '.Plaintext' | base64 > plaintext-data-key cat generate-data-key-response.json | jq -r '.CiphertextBlob' | base64 --decode > encrypted-data-key
平文データキーを使ってデータを暗号化する。
openssl aes-256-cbc -e -in plaintext-data.txt -out encrypted-data.txt -pass file:plaintext-data-key
暗号化したら、平文データキーは削除する。暗号化前のデータ(plaintext-data.txt)やCLIの戻り値を格納したファイル(generate-data-key-response.json)も削除する。
データの復号
暗号化されたデータキーを復号する。CiphertextBlobにはメタデータが含まれているため、マスターキーを指定する必要はない。
aws kms decrypt \ --ciphertext-blob fileb://encrypted-data-key > decrypt-response.json
平文データキーが返ってくるのでファイルに保存する。
cat decrypt-response.json | jq -r '.Plaintext' | base64 > decrypted-data-key
この平文データキーを使ってデータを復号する。
$ openssl aes-256-cbc -d -in encrypted-data.txt -pass file:decrypted-data-key Hello World!
復号されることが確認できた。復号できたら平文データキーは削除する。