LoginSignup
5
3

More than 3 years have passed since last update.

AWS KMSをawscliから試してみる

Posted at

KMSはAWSの他のサービスを使うときになんとなく設定する程度で、KMSそのものの動きはいままで理解できていませんでした。そこで、awscliで手動で暗号化・復号化の処理をしてみることで、理解を進めました。

キー作成

aws kms create-key コマンドでキーを作成します。

$ aws kms create-key
{
    "KeyMetadata": {
        "AWSAccountId": "123456789012",
        "KeyId": "2f94xxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx",
        "Arn": "arn:aws:kms:ap-northeast-1:123456789012:key/2f94xxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx",
        "CreationDate": 1620370256.542,
        "Enabled": true,
        "Description": "",
        "KeyUsage": "ENCRYPT_DECRYPT",
        "KeyState": "Enabled",
        "Origin": "AWS_KMS",
        "KeyManager": "CUSTOMER",
        "CustomerMasterKeySpec": "SYMMETRIC_DEFAULT",
        "EncryptionAlgorithms": [
            "SYMMETRIC_DEFAULT"
        ]
    }
}

ここで作成したキーは、存在は見えるものの、キーそのもの(CMK、Customer Master Key)を見ることはできません。

AWSアカウントにあるキー一覧を確認

aws kms list-keys コマンドでキーの一覧を確認できます。さきほど作成したキーはこの中に含まれています。

$ aws kms list-keys
{
    "Keys": [
        {
            "KeyId": "2f94xxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx",
            "KeyArn": "arn:aws:kms:ap-northeast-1:123456789012:key/2f94xxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx"
        },
        {
            "KeyId": "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx",
            "KeyArn": "arn:aws:kms:ap-northeast-1:123456789012:key/xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx"
        },
        {
            "KeyId": "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx",
            "KeyArn": "arn:aws:kms:ap-northeast-1:123456789012:key/xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx"
        },
        ...
    ]
}

マネジメントコンソールで見ると、作成したキーはCustomer managed keysに入っていました。

image.png

さきほど作成した以外のキーはAWS managed keysに入っていました。

image.png

エイリアスは aws kms list-aliases コマンドなどで確認できます。

$ aws kms list-aliases
{
    "Aliases": [
        {
            "AliasName": "alias/aws/backup",
            "AliasArn": "arn:aws:kms:ap-northeast-1:123456789012:alias/aws/backup",
            "TargetKeyId": "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx",
            "CreationDate": 1594564129.245,
            "LastUpdatedDate": 1594564129.245
        },
        {
            "AliasName": "alias/aws/dms",
            "AliasArn": "arn:aws:kms:ap-northeast-1:123456789012:alias/aws/dms",
            "TargetKeyId": "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx",
            "CreationDate": 1598578567.162,
            "LastUpdatedDate": 1598578567.162
        },
        {
            "AliasName": "alias/aws/dynamodb",
            "AliasArn": "arn:aws:kms:ap-northeast-1:123456789012:alias/aws/dynamodb",
            "TargetKeyId": "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx",
            "CreationDate": 1604415194.916,
            "LastUpdatedDate": 1604415194.916
        },
        {
            "AliasName": "alias/aws/ebs",
            "AliasArn": "arn:aws:kms:ap-northeast-1:123456789012:alias/aws/ebs"
        },
        ...

CDK作成

aws kms generate-data-key コマンドによりCDKを作成します。CDKはデータを暗号化・復号化するためのキーです。

$ aws kms generate-data-key --key-id 2f94xxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx --key-spec AES_256
{
    "CiphertextBlob": "AQID...",
    "Plaintext": "zNn6...",
    "KeyId": "arn:aws:kms:ap-northeast-1:123456789012:key/2f94xxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx"
}

レスポンスにある、Plaintextはキーそのもので、CiphertextBlobはそのキーを最初に作成したキー(CMK、Customer Master Key)で暗号化したものです。どちらもBASE64でエンコードされた長い文字列です。このあとで試しますが、aws kms decryptコマンドで、CiphertextBlobからPlaintextを復元できます。

CDKは aws kms generate-data-key コマンドを実行するごとに異なるキーが返されます。

データを暗号化

Hello, World! というテキストを暗号化してみます。データの暗号化・復号化は、awscliではなく、適当なツールを使えばよいようです。opensslを使いました。パスフレーズにさきほど作成したCDKのPlaintextを指定します。BASE64でデコードが必要です。

$ echo 'Hello, World!' | openssl enc -e -aes256 -pbkdf2 -pass file:<(echo 'zNn6...' | base64 -d) | base64
U2FsdGVkX19Qvh8L0t+zpptfNhgHX4a/RzpNB2nql9g=

openssl enc -eコマンドの -pass には、パスフレーズの書かれたファイルを file:FILEPATH のようにファイル名で指定します。ここではファイル作成の手間を惜しんで、コマンドの中に <(...) で埋め込んでいます。<(...) の中身はPlaintextをBASE64でデコードした結果です。

openssl encコマンドの出力は暗号化された結果です。バイナリなので、コンソール上に表示できるようにBASE64でエンコードしています。

暗号化したデータを保存

データベースなどにデータを暗号化して保存する際は U2FsdGVkX19Qvh8L0t+zpptfNhgHX4a/RzpNB2nql9g= という暗号化したデータとともに、CDKのCiphertextBlobの AQID.... という文字列(またはそれをBASE64でデコードしたバイナリ)を保存しておきます。CiphertextBlobのから直接データを復号化することはできません。CDKのPlaintextが必要です。Plaintextを得るには、KMSにCiphertextBlobからの復元をリクエストする必要があります。

このあとは、暗号化したデータとCiphertextBlobが保存されていることを想定して、そこからKMSを使って復号化する手順を踏みます。

CDKのPlaintextを復元

aws kms decrypt コマンドによりCDKのCiphertextBlobからPlaintextを復元します。

$ aws kms decrypt --ciphertext-blob fileb://<(echo 'AQID...' | base64 -d)
{
    "KeyId": "arn:aws:kms:ap-northeast-1:123456789012:key/2f94xxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx",
    "Plaintext": "zNn6...",
    "EncryptionAlgorithm": "SYMMETRIC_DEFAULT"
}

--ciphertext-blob オプションには fileb://FILEPATH のように、CiphertextBlobの AQID.... という文字列をBASE64でデコードしたバイナリを保存したファイル名を指定します。ここではファイル作成の手間を惜しんで、コマンドの中に <(...) で埋め込んでいます。<(...) の中身はCiphertextBlobをBASE64でデコードした結果です。

レスポンスされたPlaintextが、暗号化したときのPlaintextと一致しています。暗号化したときのパスフレーズを保存しておかなくても、KMSとCiphertextBlobから復元できることがわかります。

KMSはPlaintextを復元する際にはCMKを識別するためのKeyIdが必要なはずですが、 aws kms decrypt コマンドではKeyIdの指定が不要です。CiphertextBlobにCMKを識別するための情報が埋め込まれているらしいです。

データを復号化

openssl enc -d で復号化します。無事 Hello, World! が復元できました。

$ echo 'U2FsdGVkX19Qvh8L0t+zpptfNhgHX4a/RzpNB2nql9g=' | base64 -d | openssl enc -d -aes256 -pbkdf2 -pass file:<(echo 'zNn6...' | base64 -d)
Hello, World!

暗号化したデータは openssl enc -dコマンドの標準入力に渡しています。 U2FsdGVk... はBASE64でエンコードされた文字列ですので、標準入力前にBASE64でデコードしています。

openssl enc -dコマンドの -pass には、暗号化したときと同様にコマンドの中に <(...) で埋め込んでいます。

5
3
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
5
3