Amazon Web Services ブログ

AWS KMS が楕円曲線ディフィー・ヘルマン (ECDH) をサポート

本ブログは 2024 年 8 月 19 日に公開されたBlog ”Announcing AWS KMS Elliptic Curve Diffie-Hellman (ECDH) support” を翻訳したものです。

データ保護のために暗号化をする場合、プロトコル設計者は通常、その速度と効率性から対称鍵アルゴリズムを好みます。しかし、インターネットのような信頼されていないネットワーク上でデータを交換する場合、交換する当事者のみが同じ鍵を知ることができるようにするのは難しくなります。非対称鍵ペアとアルゴリズムは、公開鍵を信頼されていないネットワーク上で共有できるようにすることで、この問題の解決に役立ちます。そして、鍵共有方式を使用することで、2 つの当事者は、自身の秘密鍵と相手の公開鍵を組み合わせて、同じ共有シークレットを導出できます。

AWS Key Management Service (AWS KMS) が、楕円曲線 (ECC) KMS キーによる楕円曲線ディフィー・ヘルマン (ECDH) 鍵共有をサポートするようになったことを発表できることを嬉しく思います。新しい DeriveSharedSecret API アクションを使用することで、2 つの当事者間が導出された共有シークレットを使用して安全な通信チャネルを確立できるようになります。

このブログでは、新しい API アクションの概要を説明し、公開鍵のみを交換して共有シークレットを導出することで、安全な通信を確立する方法を解説します。次に、2 つの当事者間で共有シークレットを導出するために AWS KMS と OpenSSL を使用する方法を示すコマンド例を紹介します。

この新しい DeriveSharedSecret API アクションにより、お客様は相手方の公開鍵と AWS KMS 内に存在する秘密鍵を組み合わせて、共有シークレットを導出できます。この共有シークレットは、鍵導出関数 (KDF) を使用して対称暗号化鍵を作成するために使用できます。お客様は、この対称暗号化鍵を使用して、ローカルのアプリケーション内でデータを暗号化できます。

この相手方は、自身の対応する秘密鍵と AWS KMS のお客様の対応する公開鍵を組み合わせて、同じ共有シークレットを導出することができます。

2つの当事者が同じ共有シークレットを持つようになったので、交換するデータの暗号化と復号に使用できる対称暗号化鍵を生成できます。

DeriveSharedSecret は、お客様がアプリケーション内から自身の秘密鍵を使用するためのシンプルで安全な方法を提供します。これにより、楕円曲線統合暗号化方式 (ECIES) やエンドツーエンド暗号化方式 (E2EE) など、AWS KMS で保護されたキーを使用した新しい非対称暗号のユースケースが可能になります。

AWS KMS DeriveSharedSecret の概要

AWS KMS API リファレンスドキュメントでは、DeriveSharedSecret API アクションについて、さらに詳細に説明しています。次のステップは、API アクションの操作方法に関する大まかな説明です。

  1. キーのタイプに非対称、キーの使用方法にキーアグリーメント (鍵共有) を選択し、サポートされているキー仕様を 1 つ選び、楕円曲線 (ECC) KMS キーを作成します。既存の ECC キーをキーアグリーメント用に変更することはできません。
  2. 相手方に、あなたの KMS キーに定義したキー仕様に一致する ECC キーを作成してもらいます。
  3. 既存の GetPublicKey API アクションを使用して、KMS キーに関連付けられた公開鍵を取得します。
  4. 信頼できる方法を通じて、相手方と公開鍵を交換します。DeriveSharedSecret では、公開鍵を base64 エンコードされた DER 形式にしてください。
  5. 相手方の公開鍵と、指定した キーアグリーメント用キーを、入力値として使用して共有シークレットを導入します。AWS KMS が現時点でサポートする鍵共有アルゴリズムは ECDH です。
  6. 相手方は、AWS KMS から取得した公開鍵と、生成した ECC キーペアに関連付けられた秘密鍵を使用して、共有シークレットを導出します。

前述のステップの結果、両者は秘密情報を交換することなく同じ出力を得ることができます。2 つの当事者の間で交換されたのは公開鍵のみです。DeriveSharedSecret の出力は未加工の共有シークレットです。この共有シークレットは楕円曲線上の点の積であり、暗号鍵に必要なバイト数をはるかに超える可能性があります。暗号鍵をこの共有シークレットから導出するために、米国国立標準技術研究所 (NIST) SP800-56A Rev. 3 のセクション 5.8 のガイダンスに従って、KDF (鍵導出関数) を使用することをお勧めします。

本ブログでは、AWS CLI と OpenSSL コマンドラインを使用してこの手順を説明します。AWS Encryption SDK は本ブログでは詳しく説明しませんが、お客様のためのベストプラクティスを組み込んでいますので、AWS KMS ECDH キーリングもあわせてご確認ください。

ユースケース例

ECDH 鍵共有を使用したい例として、エンドツーエンド暗号化が挙げられます。セキュアな通信のためのフレームワークを提供するプロトコルは存在しますが(例えば AWS Wickr 内など)、ここではこれらのプロトコルの背後にある簡略化された主要なステップを紹介します。この例では、Alice と Bob は両方ともメッセージングネットワークの一部です。
このネットワークは中央管理型のサービスによって管理されており、このサービスは Alice や Bob の暗号化されていないメッセージにアクセスできてはいけません。

Figure 1: High-level architecture for the service described in the example use case

図 1 :ユースケース例で説明されているサービスの高レベルアーキテクチャ

図 1 に示すように、Alice と Bob はそれぞれ ECC キーペアを持ち、以下のステップで ECDH を使用して共有シークレットの導出を行います:

  1. Alice は、中央集中型キーストレージサービスに自身の公開鍵を登録します。キーストレージサービスの詳細な説明は、このブログでは扱いません。
  2. Bob は、AWS KMS ユーザーであるため、AWS KMS の GetPublicKey アクションを呼び出して、ECC KMS キーペアの公開鍵を取得します。
  3. Bob は、同じ中央集中型キーストレージサービスに自身の公開鍵を登録します。
  4. Aliceは、Bob と暗号化されたメッセージを交換するために、中央集中型キーストレージサービスから Bob の公開鍵を取得します。
  5. Bob は、Alice が彼とコミュニケーションを取りたがっていることを通知され、中央集中型キーストレージサービスから Alice の公開鍵を取得します。
  6. Alice は、Bob の公開鍵と自身の秘密鍵を使用して、自身の暗号プロバイダーを利用して共有シークレットを導出します。
  7. Bob は、Alice の公開鍵と自身の秘密鍵を使用して、DeriveSharedSecret を利用して共有シークレットを導出します。
  8. Alice と Bob は、同一の共有シークレットを持つことになります。この共有シークレットから、適切な KDF を使用して対称暗号化鍵を作成できます。この暗号鍵を使用して、Bob に送信可能な暗号文を作成できます。

ユースケース例の詳細な解説

AWS KMS を使用して ECDH 用の KMS キーを作成し、共有シークレットを導出するには、以下の手順を使用できます。説明のために、例として挙げたユースケースでは、ユーザー Alice は暗号化ツールとして OpenSSL を使用しています。以下に、AWS KMS ユーザーの Bob と OpenSSL ユーザーの Alice が、お互いの公開鍵を使用して共有シークレットを導出する方法を説明します。

一般的な前提条件

このサンプルソリューションを実装するには、以下の前提条件を満たしている必要があります:

  • AWS CLI — 最新バージョンを推奨します。ここでの例では aws-cli/2.15.40 および aws-cli/1.32.110 を使用しています。
  • OpenSSL — ここでの例では OpenSSL 3.3.0 を使用しています。
  • 両当事者(この例で使用するユースケースの Alice と Bob)が同じ楕円曲線暗号の ECC キーを持っています。次のセクション キー作成の事前準備 のステップで、これらのキーの作成方法を説明します。

キー作成の前提条件

Alice と Bob は、鍵生成時に同じ楕円曲線暗号を使用する必要があります。DeriveSharedSecret API オペレーションは、ECC_NIST_P256、ECC_NIST_P384、ECC_NIST_P521 の楕円曲線に対応しており、これらは OpenSSL ではそれぞれ P-256、P-384、P-521 に対応します。AWS KMS がサポートする楕円曲線は、米国国立標準技術研究所 (NIST) によって承認された暗号化アルゴリズムです。AWS 中国リージョン の AWS KMS は SM2 キー仕様のみサポートしています。

Bob は鍵共有の目的で KMS の非対称キーを作成

Bob は AWS KMS で CreateKey API アクションを使用してキーペアを作成します。次の例では、Bob は KeySpec パラメータに ECC_NIST_P256 を、KeyUsage パラメータに KEY_AGREEMENT を指定して ECC キーペアを作成します。

aws kms create-key \
--key-spec ECC_NIST_P256 \
--key-usage KEY_AGREEMENT \
--description "Example ECDH key pair"

レスポンスは以下のようになります:

{
    "KeyMetadata": {
        "AWSAccountId": "111122223333",
        "KeyId": "a1b2c3d4-5678-90ab-cdef-EXAMPLE11111",
        "Arn": "arn:aws:kms:us-east-1:111122223333:key/a1b2c3d4-5678-90ab-cdef-EXAMPLE11111",
        "CreationDate": "2024-06-25T13:06:24.888000-07:00",
        "Enabled": true,
        "Description": "Example ECDH key pair",
        "KeyUsage": "KEY_AGREEMENT",
        "KeyState": "Enabled",
        "Origin": "AWS_KMS",
        "KeyManager": "CUSTOMER",
        "CustomerMasterKeySpec": "ECC_NIST_P256",
        "KeySpec": "ECC_NIST_P256",
        "KeyAgreementAlgorithms": [ 
            "ECDH"
        ],
        "MultiRegion": false 
    }
}

ドキュメントの非対称 KMS キーの作成では、AWS マネジメントコンソールを使用して、上記 CLI で作成した同じプロパティを持つ KMS キーペアを作成する方法が説明されています。このサンプルでは、デフォルトの KMS キーポリシーを持つ KMS キーを作成しますが、お使いの環境に適した最小権限の原則に従って、キーポリシーを確認し、設定することを推奨します。

注: KMS キーが作成されると、アカウント内のアクティビティを監視し記録するサービスである AWS CloudTrail によってログに記録されます。AWS KMS サービスへの API コールは CloudTrail にログとして記録され、これを使用して KMS キーへのアクセスを監査できます。

KMS キーを KeyId の値ではなく人間が読みやすい文字列で識別できるようにするために、KMS キーにエイリアスを作成できます(target-key-id の値 a1b2c3d4-5678-90ab-cdef-EXAMPLE11111 を、ご自身の KeyId の値に置き換えてください)。エイリアスにより、KMS キーをより簡単に使用・管理できるようになります。

Bob は以下の CLI コマンドを使用して、KMS キーのエイリアスを作成します:

aws kms create-alias \
    --alias-name alias/example-ecdh-key \
    --target-key-id a1b2c3d4-5678-90ab-cdef-EXAMPLE11111 

Alice は OpenSSL を使用して、鍵共有のための ECC 鍵を作成

OpenSSL の ecparam および genkey オプションを使用して、Alice は P-256 ECC キーを作成します。P-256 楕円曲線は、AWS KMS では ECC_NIST_P256 となります。

注: ECDH が機能するためには、OpenSSL の ECC キーの楕円曲線が、相手方(この例では Bob)が作成した ECC KMS キーと同じ楕円曲線暗号である必要があります。

openssl ecparam -name P-256 \
        -genkey -out openssl_ecc_private_key.pem

以上で、事前準備のキー作成は完了です。

鍵交換と共有シークレット導出プロセス

このセクションでは、Alice と Bob は公開鍵を共有し、お互いの公開鍵を取得し、同じ共有シークレットを導出する手順を概説します。Alice と Bob それぞれが導出した共有シークレットを比較し、両者が同じ共有シークレットを導出したことを説明します。

ステップ 1: Alice による OpenSSL 公開鍵の生成と中央サービスへの登録

AWS KMS では 公開鍵は DER 形式ある必要があります。そのため、この例では Alice は自身の ECC 秘密鍵を使用して、以下の CLI コマンドで DER 形式の公開鍵を作成します。

openssl ec -in openssl_ecc_private_key.pem \
        -pubout -outform DER \
        > openssl_ecc_public_key.bin.der

生成されたファイルの openssl_ecc_public_key.bin.der は DER 形式の公開鍵です。Alice はこれを中央集中型キーストレージサービスに保存する(または通信したい相手に送信する)ことができます。中央集中型キーストレージサービスの詳細については、このブログでは扱いません。

ステップ 2: Bob が ECC KMS キーの公開鍵を取得

Bob は、ECC KMS キーの公開鍵を取得するために、GetPublicKey API アクションを使用します。Bob は、以下のように AWS CLI コマンド get-public-key を使用してこの API を呼び出します。

aws kms get-public-key \
    --key-id alias/example-ecdh-key \
    --output text \
    --query PublicKey | base64 --decode > kms_ecdh_public_key.der

AWS CLI コマンドで PublicKey をクエリした値は、DER 形式の X.509 公開鍵で、可読性のために base64 でエンコードされています。この base64 エンコードされた値を base64 コマンドでデコードし、デコードされた値を、ファイル kms_ecdh_public_key.der に出力しています

注: Boto3 などの AWS SDK のいずれかを使用してこの API を呼び出す場合、返される PublicKey の値は base64 エンコードされていません。

このユースケース例では、Alice は OpenSSL を使用しており、PEM 形式の公開鍵が必要です。Bob は、次のコマンドを用いて DER 形式の公開鍵を PEM 形式に変換します。

openssl ec -pubin -inform DER -outform PEM \
        -in kms_ecdh_public_key.der \
        -out kms_ecdh_public_key.pem

kms_ecdh_public_key.pem ファイルは、PEM 形式の公開鍵です。

ステップ 3: Bob が公開鍵を中央集中型キーストレージサービスに登録

Bob は、ステップ 2 で取得した PEM 形式の公開鍵を、中央集中型キーストレージサービスに保存します。

ステップ 4: Alice が共有シークレット導出のために Bob の公開鍵を取得

ECDH 鍵共有を実行するには、関係する 2 つの当事者 (この例では Alice と Bob) が互いに公開鍵を交換する必要があります。Alice は、Bob に暗号化されたメッセージを送信するために、中央集中型キーストレージサービスから Bob の公開鍵を取得します。

Bob の公開鍵である kms_ecdh_public_key.pem は、すでに OpenSSL が想定する PEM 形式になっています。

ステップ 5: Bob が共有シークレット導出のために Alice の公開鍵を取得

ECDH 鍵共有を実行するには、関係する 2 つの当事者、Alice と Bob が互いに公開鍵を交換する必要があります。Bob は Alice が彼と通信したいという通知を受け取り、中央集中型キーストレージサービスから Alice の公開鍵を取得します。

Alice の公開鍵である openssl_ecc_public_key.bin.der は、AWS KMS が想定する DER 形式にすでになっています。

ステップ 6: Alice による OpenSSL を使用した共有シークレットの導出

Alice は、自身の秘密鍵と Bob の公開鍵を使用して、OpenSSL で共有シークレットを導出できます。Alice は、OpenSSL の pkeyutl コマンドの derive オプションを使用して共有シークレットを導出します

openssl pkeyutl -derive \
        -inkey openssl_ecc_private_key.pem \
        -peerkey kms_ecdh_public_key.pem > openssl.ss

openssl.ss ファイルには、共有シークレットがバイナリ形式で格納されます。

ステップ 7: Bob による AWS KMS を使用した共有シークレットの導出

Bob は、自身の秘密鍵 (AWS KMS 内で安全に保管されています) と Alice の公開鍵を使用して、AWS KMS を通じて共有シークレットを導出できます。以下は、Bob が AWS CLI コマンド derive-shared-secret を使用して DeriveSharedSecret API アクションを実行する例です。現時点のサポートされている鍵共有アルゴリズムは ECDH です。PublicKey パラメータには Alice の公開鍵を渡します。

aws kms derive-shared-secret \
--key-id alias/example-ecdh-key \
--public-key fileb://path/to/openssl_ecc_public_key.bin.der \
--key-agreement-algorithm ECDH \
--output text --query SharedSecret | base64 --decode > kms.ss

AWS CLI を使用すると、返された SharedSecret の値は可読性のために base64 エンコードされています。base64 --decode コマンドを使用して、デコードされたバイナリ形式をファイルに保存します。

注: Boto3 などの AWS SDK のいずれかを使用してこの API を呼び出す場合、返される SharedSecret の値は base64 エンコードされていません。

kms.ss ファイルには、バイナリ形式で共有シークレットが含まれます。

ステップ 8: Alice が共有シークレットと適切な KDF を使用して、Bob への通信を暗号化するための暗号鍵を導出

次のコマンドを使用してステップ 6 と 7 でそれぞれ導出した共有シークレットの 2 つのファイルを比較し、同一であることを確認します

diff -qs openssl.ss kms.ss

これらのファイルが同一であることから、AWS KMS と OpenSSL の両方を使用して同じシークレットが導出されたことがわかります。

次のステップとして、共有シークレットを使用して、Alice は適切な 鍵導出関数 (KDF) を用いて対称暗号化鍵を導出します。この対称暗号化鍵を使用してデータを暗号化し、暗号文を Bob に送信します。

このブログでは、対称暗号化鍵を導出するステップについては説明しません。これは、ユースケースによっては複雑なトピックになる可能性があるためです。ただし、生の共有シークレットは均一ではないため、暗号鍵として使用しないでください。共有シークレットには多くのエントロピーがありますが、バイト文字列自体はランダムではありません。

NIST は、生の共有シークレット (NIST SP800-56A Rev. 3 のセクション 5.8 で説明されている値 Z) に対して KDF を使用することを推奨しています。推奨される KDF については、NIST SP800-56C Rev. 2 でより詳細に説明されています。その一例として、OpenSSL Single Step KDF (SSKDF) EVP_KDF-SS がありますが、この KDF を使用する際は、FixedInfo などの他の値を慎重に選択する必要があります。

お客様が共有シークレットに対して使用する適切な KDF を選択できるよう、AWS Encryption SDK に AWS KMS ECDH キーリング が追加されました。キーリングは、コード内に実装する AWS Encryption SDK 内の構成要素です。キーリングは、データを保護するためのベストプラクティスを適用しながら、暗号鍵の管理を処理します。キーリングを使用して、鍵交換のための KMS キーを参照し、データを暗号化する関数を呼び出すことができます。データは NIST の推奨に従って導出された共有ラッピングキーを使用して暗号化され、Encryption SDK は暗号文に キーコミットメント を適用します。

まとめ

このブログでは、2024 年 8 月に一般利用が開始された DeriveSharedSecret API アクションを使用して、安全に共有シークレットを導出する方法を紹介しました。信頼できないネットワーク上で秘密情報を共有することなく、2 つの当事者間で ECDH を使用する方法を説明しました。AWS CloudTrail ログを通じて AWS KMS キーの使用状況を追跡こともできます。共有シークレットから対称暗号化鍵を生成するには、KDF を使用する必要があることを述べました。データの暗号化には AWS Encryption SDK の使用を強くお勧めします。これは、対称暗号化鍵の生成に推奨される NIST の鍵導出関数 (KDF) を確実に使用します。

この投稿に関するフィードバックがある場合は、以下のコメントセクションにコメントを投稿してください。この投稿に関する質問がある場合は、AWS サポートにお問い合わせください。

Patrick Palmer

Patrick Palmer
Patrick は AWS のプリンシパルセキュリティスペシャリストソリューションアーキテクトです。世界中のお客様が AWS サービスを安全に使用できるよう支援し、暗号技術を専門としています。仕事以外では、成長する家族と過ごす時間とビデオゲームを楽しんでいます。

Raj Puttaiah

Raj Puttaiah
Raj は AWS KMS のソフトウェア開発マネージャーです。運用の卓越性に焦点を当てて、AWS KMS の機能開発をリードしています。仕事以外では、ワシントン州の美しい自然の中で家族とハイキングを楽しんだり、2 人の息子の活動に同行したりして時間を過ごしています。

Michael Miller

Michael Miller
Michael はアイルランドを拠点とする AWS のシニアソリューションアーキテクトです。英国とアイルランドの公共部門のお客様のクラウド導入を加速させるのを支援し、セキュリティとネットワーキングを専門としています。以前の役職では、サービスプロバイダー、コンサルティング、金融サービス組織など、さまざまな分野でのアーキテクチャ設計と実装支援を担当してきました。

本ブログは Security Solutions Architect の 中島 章博 が翻訳しました。