Amazon Web Services ブログ

AWS KMS の新機能 公開鍵暗号によるデジタル署名

AWS Key Management Service で公開鍵暗号をサポートするようになりました。AWS SDK の新しい API を使ってアプリケーションデータを保護するために公開鍵、秘密鍵のキーペアを作成、管理、利用することが可能になりました。既に提供されている共通鍵暗号機能と同様に、公開鍵暗号の秘密鍵は KMS サービスの外側には出ないカスタマーマスターキー(CMK)として生成出来ます。また、データキーとしても生成可能で、データキーの秘密鍵の部分はアプリケーションに CMK で暗号化して渡すことが可能です。公開鍵 CMK の秘密鍵の部分は、AWS KMS のハードウェアセキュリティモジュールに格納されるため、AWS 従業員を含む誰も平文のキーマテリアルにアクセスすることは出来ません。AWS KMS のサポートする公開鍵のタイプは、 RSA 2048, RSA 3072, RSA 4096, ECC NIST P-256, ECC NIST P-384, ECC NIST-521, ECC SECG P256k1となります。

リリースの背景

システム間でデジタルメッセージの整合性を保証する一般的な方法はデジタル署名です。送信者は元のメッセージに暗号アルゴリズムに基づいた暗号鍵を使ってデータ構造を追加します。これにより、暗号鍵にアクセス出来る受信者は暗号学的にメッセージが改変されていないことを確認できます。受信者が送信者が使ったのと同じ暗号鍵にアクセス出来ない場合に、公開鍵暗号によるデジタル署名の仕組みが役立ちます。送信者は鍵の公開部分をすべての受信者に公開できますが、送信者は鍵の秘密部分を使って署名をコントロールすることが引き続き可能です。公開鍵暗号は信頼されたソースコードや認証認可用のトークン、文書の電子署名、エレクトリックコマースのトランザクション、セキュアメッセージングなどに利用されています。AWS KMS は 基本的なデジタル署名と言われている機能をサポートします。これは署名オブジェクトの中に ID 情報が含まれていないものです。一般的に ID 情報をデジタル署名に添付する方式はデジタル証明書です。もしお客様のアプリケーションが署名や署名確認のためにデジタル証明書を必要としている場合には、AWS Certificate Manager のプライベート CA 機能をおすすめします。 このサービスはデジタル署名アプリケーションのためにプログラム的に暗号鍵を含んだ証明書を作成してデプロイする機能を提供します。典型的なデジタル証明書を使うアプリケーションは、Webサーバー上で通信をセキュアにするために使われるTLS 処理です。

AWS KMS を使ったファイルの署名と確認

AWS アカウント上にあるアプリケーション A がアプリケーション B にファイルを送信する例を考えてみましょう。アプリケーションBがファイルを受信するときにデジタル署名を使って、送信途中でファイルが改ざんされていないことを確認したいと想定します。また、アプリケーション A が送信するファイルに暗号鍵を使って署名することで、アプリケーション B が A 以外の送信者から送られたファイルを A から受信したと誤って受信することを回避したいと想定します。AWS KMS は公開鍵暗号の秘密部分を KMS サービスの外側や承認されていないユーザーにはエクスポート出来ない仕組みになっているので、お客様はアプリケーション A だけが正しく暗号鍵を使って署名出来るというポリシーをきめて、強制することが可能です。

手順としては、はじめに、アプリケーション A はファイルそのもの、あるいは、ファイルのダイジェストを AWS KMS の公開鍵 CMK に対する署名 API に送信します。ファイルの大きさが 4KB 以下であれば AWS KMS はファイルのダイジェストを署名処理の中で生成することが可能です。もし、ファイルの大きさが 4KB 以上だった場合には、アプリケーション上で作ったダイジェストのみを送信し、AWS KMS にリクエストの中にメッセージタイプパラメータにダイジェストを入れて送信していることを伝える必要があります。お客様は、ファイルのダイジェストを作るためにいくつかのハッシュ関数を使うことが可能ですが、受信側のアプリケーション B がファイルの整合性検証のために同じハッシュ関数を利用可能である必要があります。今回の例では、ハッシュ関数に SHA256 を使います。ファイルのダイジェストが出来たら、AWS KMS は CMK の中の秘密部分を利用して、API リクエストで指定された署名アルゴリズムでダイジェストを暗号化します。この暗号結果はバイナリデータオブジェクトであり、このブログの中では”署名”と呼びます。

アプリケーション B が署名つきのファイルを受信すると、アプリケーション B はファイルのダイジェストを作成します。それから、新しいダイジェストと署名オブジェクト、使われた署名アルゴリズム、CMK のキー ID を検証用の API に送信します。AWS KMS はリクエストに対応した CMK の公開部分と検証リクエストで指定された署名アルゴリズムを使います。検証用のAPIに送信するのではなく、アプリケーション B がアプリケーション上で公開鍵を使って署名を検証することも可能です。後者の方法はアプリケーション B が AWS KMS にリクエストを送るための AWS 認証情報を入手して保持する方法が無い場合に有用です。しかしながら、この方法はアプリケーション B が暗号アルゴリズムにアクセス出来ることが必要で、CMK の公開部分を入手することが出来ることが必要です。今回の例では、アプリケーション B はアプリケーション A と同じアカウントにありますので、検証用の API リクエストに必要な AWS 認証情報を得ることが可能です。このポストの後半で具体的な署名検証方法について2つの方式でどのように実行するのかを説明します。

署名用の暗号鍵の作成とキーの権限ポリシーのセットアップ

最初に、公開鍵 CMK を作成する必要があります。CreateKey API を呼び出すときに、CustomerMasterKeySpec パラメータにどれか1つの公開鍵暗号のスペックを渡す必要があります。この例では、ECC_NIST_p384を鍵のスペックとして選択します。この鍵タイプは楕円曲線暗号アルゴリズムと呼ばれるもので、従来の RSA ベースのアルゴリズムよりもより効率的です。

公開鍵 CMK の作成の中で、どの暗号操作をアプリケーション A と B が利用する AWS プリンシパルに利用可能にするか制御するためのリソースポリシーを鍵にアタッチする必要があります。ベストプラクティスとして、権限の最小化のためにそれぞれのアプリケーションに別々の IAM プリンシパルを用意して使うとにします。この例では、アプリケーション A はファイルの署名のみ、アプリケーション B は署名の検証のみにするべきです。ここでは、それぞれのアプリケーションは Amazon EC2 上で稼働しているものとします。そのため、複数の IAM ロールを作成します。

アプリケーション A の IAM ロール(署名ロール)に CMKキーポリシーの kms:Sign 権限を付与する

アプリケーション B の IAM ロール(検証ロール)に CMKキーポリシーの kms:Verify 権限を付与する

署名を許可する CMK キーポリシードキュメントの記述は以下のようになります。(アカウント ID の “111122223333” はご自身のものに置き換えてください)

{
	"Sid": "Allow use of the key for digital signing",
	"Effect": "Allow",
	"Principal": {"AWS":"arn:aws:iam::<111122223333>:role/SignRole"},
	"Action": "kms:Sign",
	"Resource": "*"
}

検証を許可する CMK キーポリシードキュメントの記述は以下のようになります。(アカウント ID の “111122223333” はご自身のものに置き換えてください)

{
	"Sid": "Allow use of the key for verification",
	"Effect": "Allow",
	"Principal": {"AWS":"arn:aws:iam::<111122223333>:role/VerifyRole"},
	"Action": "kms:Verify",
	"Resource": "*"
}

署名ワークフロー

公開鍵 CMK と IAM ロールを作成したので、ファイルに署名する準備が出来ました。アプリケーション A はファイルのメッセージダイジェストを生成し、AWS KMS に CMK のキー ID と署名アルゴリズムをつけて署名リクエストを送信します。実行するための CLI コマンドは以下のようになります。key-id パラメータはご自身の環境のキー ID に置き換えてください。

aws kms sign \
	--key-id <1234abcd-12ab-34cd-56ef-1234567890ab> \
	--message-type DIGEST \
	--signing-algorithm ECDSA_SHA_256 \
	--message fileb://ExampleDigest

ここでは、ECDSA_SHA_256 の署名アルゴリズムを使っています。サポートされている署名アルゴリズムについては Sign API のドキュメントを見てください。 API コールを呼び出している認証情報が 署名ロールと合致することが確認されると、KMS はダイジェストから署名を生成し、CMK キー IDと署名、署名アルゴリズムを返します。

検証ワークフロー 1 : 検証 API を呼ぶパターン

アプリケーション B がファイルと署名を受信すると、受信したファイルの SHA 256 ダイジェストを算出します。そして、AWS KMS に対する検証リクエストを新しいダイジェスト、 アプリケーション A から受信した署名、署名アルゴリズム、CMK キー ID と共に作成します。この手順を実行する CLI コマンドは下記ようになります。key-id パラメータをご自身の環境の CMK キー ID に置き換えてください。

aws kms verify \
	--key-id <1234abcd-12ab-34cd-56ef-1234567890ab> \
	--message-type DIGEST \
	--signing-algorithm ECDSA_SHA_256 \
	--message fileb://ExampleDigest \
	--signature fileb://Signature

検証リクエストが権限認可されていることが確認されると、AWS KMS は CMK の公開部分を使用して署名の復号を行い署名を検証します。そして、復号された結果と検証リクエストの中のダイジェストを比較します。一致した場合には、 SignatureValid のブーリアン値として True を返します。これは、受信者が生成したダイジェストと送信者が送ってきたダイジェストが一致していることを意味します。オリジナルのダイジェストはファイルに対してユニークになるので、受信者はファイルが送信途中で改ざんされていないことを確認出来ます。

AWS KMS の 検証 API を用いる利点の1つは、API 呼び出し側が、署名を作るのに使われた秘密鍵と対にになっている公開鍵を探す必要がないことです。API 呼び出し側は、CMK のキー ID と使われている署名アルゴリズムを知っているだけで良いです。また、AWS KMS へのリクエストは全て AWS CloudTrail に記録されているので、署名と検証の操作が期待した通りに行われていることを監査可能です。 さらに利用可能なパラメータについて詳しく知りたい場合には Verify API のドキュメントを参照してください。

検証ワークフロー 2 : 公開鍵を使ってローカルで検証する

Verify API を直接呼ぶのではなく、AWS KMS の GetPublicKey API を使って CMK の中にある公開鍵を取り出して署名をローカルで検証する選択肢もあります。アプリケーション B が複数の署名を高速に検証したい、かつ検証 API をネットワーク経由で毎回呼び出したくない場合に、この方法を選択する可能性があります。この方法では、アプリケーション B は AWS KMS にGetPublicKey リクエストを送信して公開鍵を取り出します。CLI コマンドの例は下記のようになります。key-id パラメータはご自身の環境の CMK のキー ID に読み替えてください。

aws kms get-public-key \
--key-id <1234abcd-12ab-34cd-56ef-1234567890ab>

アプリケーション B が AWS KMS に GetPublicKey リクエストを送信するには権限が必要なことに注意してください。公開鍵のダウンロードを許可する VerifyRole 用の CMK キーポリシー文書の書式は、下記のようになります(アカウントID “111122223333” はご自身のものに読み替えてください)。

{
	"Sid": "Allow retrieval of the public key for verification",
	"Effect": "Allow",
	"Principal": {"AWS":"arn:aws:iam::<111122223333>:role/VerifyRole"},
	"Action": "kms:GetPublicKey ",
	"Resource": "*"
}

アプリケーション B が公開鍵を入手すると、ローカル環境で最適な暗号プロバイダを使用して署名検証を実行することが出来ます。アプリケーション B は公開鍵とそれぞれの署名オブジェクトの署名アルゴリズムを把握している必要があります。異なる公開鍵を使うアプリケーション A からの署名の復号は失敗し、署名検証操作は失敗します。

利用可能なリージョンと料金

AWS KMS における公開鍵暗号の作成と操作は、バージニア北部、シドニー、アイルランド、オレゴン、そして東京リージョンで利用可能です。また、他のリージョンについてはこれからリリースすることが計画されています。新機能の料金については AWS KMS の料金ページをご覧ください。

サマリー

このブログでは、 デジタル署名とその検証を新しい AWS KMS API で実行する例を紹介しました。 AWS KMS による公開鍵暗号の秘密部分の生成と格納を、AWS KMS に実行されることで、 IAM プリンシパルを持っているユーザーやアプリケーションのみに署名用暗号鍵の利用を制限出来ます。 OIDC IDトークン、OAuth 2.0アクセストークン、文書、構成ファイル、システムアップデートメッセージ、監査ログなどはこの機能を使った署名と検証のユースケースになります。

また、KMS がリリース当初から提供されている共通鍵 CMK を使った処理の代替として、公開鍵 CMK を使った暗号化や復号も可能です。利用者は、AWS KMS に公開鍵のキーペアを生成して渡すようにリクエストすることが可能です。そしてキーペアを使ってデータの暗号化や復号が可能です。このようなユースケースの情報ついては、将来のAWS セキュリティブログをお待ちください。 公開鍵暗号のさらに詳しい情報については AWS ドキュメントページを参照してください。

もし、公開鍵暗号の機能について質問がありましたら、AWS KMS ディスカッションフォーラムで新しいスレッドを作成してください。

原文のブログはこちらにあります。 https://aws.amazon.com/blogs/security/digital-signing-asymmetric-keys-aws-kms/

このブログの翻訳はSA 高橋 が実施しました。