AWS KMSで公開鍵暗号してみた

AWS Key Management Service(KMS)は2019年末に非対称鍵にサポートするようになりました。 非対称鍵は

  • データの暗号・復号
  • デジタル署名の署名・検証

などに利用できます。

今回は、KMSの非対称鍵を利用してデータを暗号・復号(公開鍵暗号)する方法を紹介します。

後者のデジタル署名については、以下のブログを参照ください。

対称鍵と非対称鍵の暗号化の使い分け

AWS KMSでは従来から対称鍵を利用した暗号・復号にも対応していました。 違いを確認します。

対称鍵暗号は以下の流れで暗号・復号します。

  1. [暗号データの受信者]対称鍵を作成
  2. [暗号データの作成者]対称鍵を使ってデータを暗号化
  3. [暗号データの作成者]暗号文を受信者に送付
  4. [暗号データの受信者]暗号文を対称鍵で復号

対称鍵のポイントは、暗号と復号で同じ鍵を利用することです。

一方で、非対称鍵を利用する公開鍵暗号は以下の流れで暗号・復号します。

  1. [暗号データの受信者]公開鍵のキーペアを作成
  2. [暗号データの受信者]暗号データの作成者に公開鍵を送付
  3. [暗号データの作成者]公開鍵を使ってデータを暗号化
  4. [暗号データの作成者]暗号文を受信者に送付
  5. [暗号データの受信者]暗号文を秘密鍵で復号

公開鍵暗号のポイントは

  • 暗号と復号で異なる鍵を利用
  • 暗号に利用する公開鍵はだれでもアクセス可能
  • 復号に利用する秘密鍵は受信者だけがアクセス可能

ということです。

AWS KMSに置き換えてみます。

従来の対称鍵暗号では、暗号復号時にKMSの対称鍵へのアクセス権限が必要でした。

公開鍵暗号では、復号時にはKMSの秘密鍵へのアクセスが必要ですが、暗号時にはキー生成後にダウンロード可能な公開鍵だけが必要です。AWSへのアクセスは不要です。

そのため、AWSに閉じて暗号・復号する場合は対称暗号(共通鍵暗号)、AWS外で発生するデータを暗号化し、AWS側で復号化する場合は非対称暗号(公開鍵暗号)が向いています。

RSA_OAEPで暗号化する

任意のデータを送信すると、それを暗号文とみなして復号化し、返信してくれるサービスを攻撃者が利用できることを仮定した攻撃を「選択暗号文攻撃(Chosen-ciphertext Attack/CCA)」と呼びます。

生RSA暗号はCCA攻撃に安全でないことが知られています。

そこで、攻撃に対して安全になるように改良されたのが RSA_OAEP です。 RSA_OAEP では平文をOAEPパディング後、 RSA暗号します。

AWS KMSの公開鍵暗号はこの RSA_OAEP アルゴリズム、具体的には

  • RSAES_OAEP_SHA_1
  • RSAES_OAEP_SHA_256

のみに対応しています。

生RSA には対応していない点にご注意ください。

Q: どのような種類の非対称暗号化アルゴリズムがサポートされていますか?

AWS KMS では、RSAES_OAEP_SHA_1 と RSAES_OAEP_SHA_256 の暗号化アルゴリズムおよび RSA 2048、RSA 3072、RSA 4096 のキータイプをサポートしています。暗号化アルゴリズムは、楕円曲線キータイプ (ECC NIST P-256、ECC NIST P-384、ECC NIST-521、ECC SECG P-256k1) と一緒に使用することはできません。

https://aws.amazon.com/kms/faqs/

AWS KMSの公開鍵で暗号化してみる

AWS KMSで非対称鍵を作成し、公開鍵暗号で暗号・復号してみます。

公開鍵暗号用の鍵の作成

公開鍵暗号用の鍵を作成するには、「キーのタイプ」に「非対称鍵」を選択し、「キーの使用」に「暗号化および復号化」を選択します。

上述の通り、「キーの仕様」で指定するキーのビット長によって、暗号化可能なデータサイズが異なります。

データの暗号化

公開鍵暗号では、公開鍵で暗号化します。

鍵の詳細画面の「パブリックキー」タブから公開鍵をダウンロードします。

なお、このフローに従い作成される鍵の秘密鍵はカスタマーマスターキー(CMK)です。 KMSサービスの外側に出ることはありません。

次に、ダウンロードした公開鍵を利用し、RSA_OAEP方式で暗号化します。

opensslコマンドを利用すると、オプションを調べる労力と引き換えに、暗号化処理を簡単に行えます。

RSAES_OAEP_SHA_256 アルゴリズムで暗号化してみます。

$ openssl version
OpenSSL 1.0.2t  10 Sep 2019
$ echo hello world! > plaintext
$ openssl pkeyutl -in plaintext \
  -encrypt -pubin \
  -inkey Publickey-xxx-xxx-xxx.pem \
  -pkeyopt rsa_padding_mode:oaep \
  -pkeyopt rsa_oaep_md:sha256 \
  -pkeyopt rsa_mgf1_md:sha256 > ciphertext

重要なオプションを解説します。

  • -in : 暗号化するファイル
  • -inkey : 暗号化に利用する公開鍵ファイル
  • -pkeyopt : RSA_OAEP_SHA_256 アルゴリズム用のオプション

データの復号化

復号には kms::decrypt API を利用します。

重要なオプションを解説します。

  • --key-id : 暗号時に利用した鍵
  • --ciphertext-blob : 暗号文
  • --encryption-algorithm : 暗号アルゴリズム
$ aws kms decrypt \
  --key-id alias/rsa \
  --ciphertext-blob fileb://ciphertext \
  --encryption-algorithm RSAES_OAEP_SHA_256
{
    "KeyId": "arn:aws:kms:eu-central-1:1234:key/aa-bb-cc-de",
    "Plaintext": "aGVsbG8gd29ybGQhCg==",
    "EncryptionAlgorithm": "RSAES_OAEP_SHA_256"
}

復号化された平文(レスポンスの Plaintext)は base64 エンコードされています。

base64 デコードして、メッセージを確認します。

$ echo aGVsbG8gd29ybGQhCg== | base64 -D
hello world!

期待通り復号化されています。

AWS API で暗号化

openssl コマンドを使わずに、AWS REST APIのkms::encrypt で暗号化することも出来ます。

$ aws kms encrypt \
    --key-id alias/rsa \
    --encryption-algorithm RSAES_OAEP_SHA_256 \
    --plaintext fileb://plaintext
{
    "CiphertextBlob": "...",
    "KeyId": "arn:aws:kms:eu-central-1:1234:key/aa-bb-cc-de",
    "EncryptionAlgorithm": "RSAES_OAEP_SHA_256"
}

対称鍵の時は、鍵(--key-id)を指定するだけで暗号化されました。 非対称鍵の時は、OAEP用のアルゴリズム(--encryption-algorithm)も指定します。

暗号文はレスポンスの CiphertextBlob にあり、base64 エンコードされています。

デコードした上でファイル保存します。

$ aws kms encrypt \
  --key-id alias/rsa \
  --encryption-algorithm RSAES_OAEP_SHA_256 \
  --plaintext fileb://plaintext \
  --output text \
  --query CiphertextBlob | base64 -D > ciphertext_cli

この暗号文を kms::decrypt で復号化してみます。

$ aws kms decrypt \
  --key-id alias/rsa \
  --ciphertext-blob fileb://ciphertext_cli \
  --encryption-algorithm RSAES_OAEP_SHA_256 \
  --output text \
  --query Plaintext | base64 -D
hello world!

期待通り復号化されています。

制限

暗号・復号に利用できる非対称鍵

AWS KMSが提供する非対称鍵は

  • RSA系
  • 楕円曲線系

の2種類があります。

この内、暗号・復号に対応しているのはRSA系のみです。

暗号化できるデータサイズ

RSA鍵と暗号アルゴリズムによって、暗号化できる平文の最大データサイズが異なります。

キー仕様 RSAES_OAEP_SHA_1 RSAES_OAEP_SHA_256
RSA_2048 214 190
RSA_3072 342 318
RSA_4096 470 446

※単位はバイト

参考までに、対称鍵が暗号化できる最大長は4096バイトです。

公開鍵暗号は遅くて大きいデータを暗号化できない

公開鍵暗号は処理に時間がかかり、暗号化できるデータサイズも小さいという制約があります。

そのため、例えば エンベロープ暗号を採用し、AES のような高速な対称暗号でデータを暗号後、AESで利用したデータキーを公開鍵で暗号化すると、様々なサイズのデータを暗号化出来ます。

最後に

AWS KMSは非対称暗号の公開鍵暗号に対応しています。 公開鍵暗号では、AWS KMSと通信せずに、公開鍵だけで暗号化します。 そのため、AWS外で発生するデータを公開鍵で暗号化し、AWS KMSで管理された秘密鍵で復号化するといった運用が可能です。

暗号化の際には、選択暗号文攻撃に対して安全になるために、RSA OAEPアルゴリズムで暗号化する点にご留意してください。

それでは。

参考