チュートリアル: Azure Key Vault を使用して BLOB を暗号化および復号化する

このチュートリアルでは、クライアント側の暗号化を使用して、Azure Key Vault に格納されているキーを使用して BLOB の暗号化および暗号化解除を行う方法について説明します。

Azure Blob Storage では、サービス側とクライアント側の両方の暗号化がサポートされています。 ほとんどのシナリオでは、データの保護で使いやすいようにサービス側の暗号化機能を使用することをお勧めします。 サービス側暗号化の詳細については、「保存データに対する Azure Storage 暗号化」をご覧ください。

.NET 用 Azure Blob Storage クライアント ライブラリは、Azure Storage にアップロードする前にアプリケーション内のデータを暗号化する作業と、クライアントにダウンロードするときにデータの暗号化を解除する作業を支援します。 また、このライブラリは Azure Key Vault との統合にも役立ち、キー管理に利用することができます。

このチュートリアルでは、次の操作方法について説明します。

  • Azure Key Vault リソースのアクセス許可を構成する
  • .NET クライアント ライブラリを使用してリソースを操作するコンソール アプリケーションを作成する
  • キー コンテナーにキーを追加する
  • キー コンテナーに格納されているキーを使用してクライアント側の暗号化オプションを構成する
  • クライアント側の暗号化を有効にした BLOB サービス クライアント オブジェクトを作成する
  • 暗号化された BLOB をアップロードし、ダウンロードした後、BLOB の暗号化を解除する

前提条件

Microsoft Entra ユーザーにロールを割り当てる

ローカルで開発する場合、キー コンテナーにアクセスするユーザー アカウントに適切なアクセス許可が付与されていることを確認します。 キーを作成し、キー コンテナー内のキーに対してアクションを実行するには、Key Vault Crypto Officer ロールが必要です。 Azure portal、Azure CLI、または Azure PowerShell を使用して、ユーザーに Azure RBAC ロールを割り当てることができます。 ロールの割り当てに使用できるスコープの詳細は、スコープの概要ページでご覧いただけます。

このシナリオでは、最小限の特権の原則に従って、キー コンテナーに限定したアクセス許可をユーザー アカウントに割り当てます。 この方法を使って、ユーザーに必要最小限のアクセス許可のみを与え、より安全な運用環境を作成します。

次の例は、Key Vault Crypto Officer ロールを割り当てる方法を示しています。これにより、このチュートリアルを完了するために必要なアクセス権が提供されます。

重要

ほとんどの場合、ロールの割り当てが Azure に反映されるまでの時間は 1 分から 2 分ですが、まれに 8 分程度までかかる場合があります。 初めてコードを実行したときに認証エラーを受け取る場合は、しばらく待ってから再試行してください。

  1. Azure portal で、メインの検索バーまたは左側のナビゲーションを使用して、お使いのキー コンテナーを見つけます。

  2. キー コンテナーの [概要] ページの左側にあるメニューで、[アクセス制御 (IAM)] を選択します。

  3. [アクセス制御 (IAM)] ページで、[ロールの割り当て] タブを選びます。

  4. 上部のメニューから [+ 追加] を選択し、次に結果のドロップダウン メニューから [ロールの割り当ての追加] を選択します。

    A screenshot showing how to assign a role in Azure portal.

  5. 検索ボックスを使って、結果を目的のロールに絞り込みます。 この例では、Key Vault Crypto Officer を検索し、一致する結果を選択して、[次へ] を選択します。

  6. [アクセスの割り当て先] で、[ユーザー、グループ、またはサービス プリンシパル] を選び、[+ メンバーの選択] を選びます。

  7. ダイアログで、自分の Microsoft Entra ユーザー名 (通常は user@domain メール アドレス) を検索し、ダイアログの下部にある [選択] を選びます。

  8. [レビューと割り当て] を選んで最終ページに移動し、もう一度 [レビューと割り当て] を行ってプロセスを完了します。

プロジェクトの設定

  1. コンソール ウィンドウ (PowerShell、Bash など) で、dotnet new コマンドを使用して、BlobEncryptionKeyVault という名前の新しいコンソール アプリを作成します。 このコマンドにより、1 つのソース ファイルを使用する単純な "Hello World" C# プロジェクトが作成されます。Program.cs

    dotnet new console -n BlobEncryptionKeyVault
    
  2. 新しく作成された BlobEncryptionKeyVault ディレクトリに切り替えます。

    cd BlobEncryptionKeyVault
    
  3. 目的のコード エディターでプロジェクトを開きます。 プロジェクトを開くには、次の手順を実行します。

    • Visual Studio で、BlobEncryptionKeyVault.csproj ファイルを見つけてダブルクリックします。
    • Visual Studio Code で、次のコマンドを実行します。
    code .
    

この例で Azure サービスを操作するには、dotnet add package を使用して次のクライアント ライブラリをインストールします。

dotnet add package Azure.Identity
dotnet add package Azure.Security.KeyVault.Keys
dotnet add package Azure.Storage.Blobs

次の using ディレクティブを追加します。必ず System.Configuration への参照をプロジェクトに追加してください。

using Azure;
using Azure.Core;
using Azure.Identity;
using Azure.Security.KeyVault.Keys;
using Azure.Security.KeyVault.Keys.Cryptography;
using Azure.Storage;
using Azure.Storage.Blobs;
using Azure.Storage.Blobs.Models;
using Azure.Storage.Blobs.Specialized;

環境変数を設定する

このアプリケーションでは、KEY_VAULT_NAME という名前の環境変数を探して、キー コンテナーの名前を取得します。 この環境変数を設定するには、コンソール ウィンドウを開いて、お使いのオペレーティング システムの手順に従います。 <your-key-vault-name> は、実際のキー コンテナーの名前に置き換えます。

Windows:

Windows の環境変数は、コマンド ラインから設定できます。 ただし、この方法を使うと、そのオペレーティング システム上で実行されているすべてのアプリケーションから値にアクセスできるため、競合が発生しないように注意する必要があります。 環境変数は、ユーザー レベルまたはシステム レベルのいずれかで設定できます。

setx KEY_VAULT_NAME "<your-key-vault-name>"

Windows で環境変数を追加した後、コマンド ウィンドウの新しいインスタンスを開始する必要があります。 Windows で Visual Studio を使用している場合は、変更を検出するための環境変数を作成した後で、Visual Studio の再起動が必要になることがあります。

Linux:

export KEY_VAULT_NAME=<your-key-vault-name>

Azure Key Vault でキーを追加する

この例では、Azure Key Vault クライアント ライブラリを使用して、キーを作成し、それをキー コンテナーに追加します。 Azure CLIAzure portal、または PowerShell を使用してキーを作成し、キー コンテナーに追加することもできます。

次のサンプルでは、指定したコンテナー用の KeyClient オブジェクトを作成します。 次に、KeyClient オブジェクトを使用して、指定したコンテナーに新しい RSA キーを作成します。

var keyName = "testRSAKey";
var keyVaultName = Environment.GetEnvironmentVariable("KEY_VAULT_NAME");

// URI for the key vault resource
var keyVaultUri = $"https://{keyVaultName}.vault.azure.net";

TokenCredential tokenCredential = new DefaultAzureCredential();

// Create a KeyClient object
var keyClient = new KeyClient(new Uri(keyVaultUri), tokenCredential);

// Add a key to the key vault
var key = await keyClient.CreateKeyAsync(keyName, KeyType.Rsa);

キーとキー リゾルバー インスタンスを作成する

次に、コンテナーに追加したばかりのキーを使用して、暗号化クライアントとキー リゾルバー インスタンスを作成します。 CryptographyClient は、IKeyEncryptionKey を実装し、Azure Key Vault に格納されているキーを使用して暗号化操作を実行するために使用されます。 KeyResolver は、IKeyEncryptionResolver を実装し、キー識別子からキー暗号化キーを取得してキーを解決します。

// Cryptography client and key resolver instances using Azure Key Vault client library
CryptographyClient cryptoClient = keyClient.GetCryptographyClient(key.Value.Name, key.Value.Properties.Version);
KeyResolver keyResolver = new (tokenCredential);

暗号化に使用するキーがコンテナー内に既にある場合、URI で渡すことにより、キーとキー リゾルバー インスタンスを作成できます。

var keyVaultKeyUri = $"https://{keyVaultName}.vault.azure.net/keys/{keyName}";
CryptographyClient cryptoClient = new CryptographyClient(new Uri(keyVaultKeyUri), tokenCredential);

暗号化オプションを構成する

次に、BLOB のアップロードとダウンロードに使用する暗号化オプションを構成する必要があります。 クライアント側の暗号化を使用するには、最初に ClientSideEncryptionOptions オブジェクトを作成し、クライアントの作成時に SpecializedBlobClientOptions を使用して設定します。

ClientSideEncryptionOptions クラスは、クライアント側の暗号化を使用して Blob Storage に接続するためのクライアントの構成オプションを提供します。 KeyEncryptionKey はアップロード操作に必要なもので、生成されたコンテンツ暗号化キーをラップするために使用されます。 KeyResolver はダウンロードに必要なもので、適切なキー暗号化キーを取り込んで、ダウンロードされたコンテンツの暗号化キーをラップ解除します。 KeyWrapAlgorithm はアップロード操作に必要なもので、コンテンツ暗号化キーをラップするときに使用するアルゴリズム識別子を指定します。

重要

バージョン 1 のセキュリティの脆弱性のために、version パラメーターに ClientSideEncryptionOptions を使用して ClientSideEncryptionVersion.V2_0 オブジェクトを作成することをお勧めします。 アプリケーションで脆弱性を軽減する方法の詳細については、「アプリケーションのセキュリティの脆弱性を軽減する」を参照してください。 このセキュリティ脆弱性の詳細については、セキュリティの脆弱性に対処するために Azure Storage で行われた SDK のクライアント側暗号化の更新に関するページを参照してください。

// Configure the encryption options to be used for upload and download
ClientSideEncryptionOptions encryptionOptions = new (ClientSideEncryptionVersion.V2_0)
{
    KeyEncryptionKey = cryptoClient,
    KeyResolver = keyResolver,
    // String value that the client library will use when calling IKeyEncryptionKey.WrapKey()
    KeyWrapAlgorithm = "RSA-OAEP"
};

// Set the encryption options on the client options.
BlobClientOptions options = new SpecializedBlobClientOptions() { ClientSideEncryption = encryptionOptions };

クライアント側の暗号化を使用するようにクライアント オブジェクトを構成する

この例では、BlobServiceClient オブジェクトにクライアント側の暗号化構成オプションを適用します。 サービス クライアント レベルで適用する場合、これらの暗号化オプションは、サービス クライアントからコンテナー クライアントに渡され、コンテナー クライアントから BLOB クライアントに渡されます。 BlobClient オブジェクトでアップロードまたはダウンロード操作が実行されると、Azure Blob Storage クライアント ライブラリでは、エンベロープ暗号化を使用して、クライアント側の BLOB を暗号化および暗号化解除します。 エンベロープ暗号化では、キーの暗号化を 1 つ以上の追加キーを使用して行います。

// Create a blob client with client-side encryption enabled.
// Attempting to construct a BlockBlobClient, PageBlobClient, or AppendBlobClient from a BlobContainerClient
// with client-side encryption options present will throw, as this functionality is only supported with BlobClient.
Uri blobUri = new (string.Format($"https://{accountName}.blob.core.windows.net"));
BlobClient blob = new BlobServiceClient(blobUri, tokenCredential, options).GetBlobContainerClient("test-container").GetBlobClient("testBlob");

BLOB の暗号化とアップロード

BlobClient オブジェクトでアップロード メソッドが呼び出されると、クライアント側の暗号化を実行するためのいくつかのステップが発生します。

  1. Azure Storage クライアント ライブラリによって、16 バイトのランダムな初期化ベクトル (IV) と 32 バイトのランダムなコンテンツ暗号化キー (CEK) が生成され、この情報を使用して BLOB データのエンベロープ暗号化が実行されます。
  2. BLOB データが、CEK を使用して暗号化されます。
  3. 次に、CEK が、ClientSideEncryptionOptions で指定したキー暗号化キー (KEK) を使用してラップ (暗号化) されます。 この例では、KEK は、指定された Azure Key Vault リソースに格納されている非対称キー ペアです。 BLOB クライアント自体は KEK にアクセスすることはなく、Key Vault によって提供されるキー ラップ アルゴリズムを呼び出すだけです。
  4. 次に、暗号化された BLOB データがストレージ アカウントにアップロードされます。

BLOB を暗号化し、Azure ストレージ アカウントにアップロードするには、次のコードを追加します。

// Upload the encrypted contents to the blob
Stream blobContent = BinaryData.FromString("Ready for encryption, Captain.").ToStream();
await blob.UploadAsync(blobContent);

BLOB がアップロードされたら、ストレージ アカウント内の BLOB を表示して、暗号化されたコンテンツと暗号化メタデータを確認できます。

BLOB の復号化とダウンロード

Azure Storage クライアント ライブラリでは、ユーザーが KEK をローカルまたはキー コンテナーのいずれかで管理していることを前提としています。 ユーザーは、暗号化に使用された特定のキーを把握しておく必要はありません。 BLOB データをダウンロードして暗号化解除するときにキー識別子を解決するには、ClientSideEncryptionOptions で指定されたキー リゾルバーが使用されます。

BlobClient オブジェクトでダウンロード メソッドが呼び出されると、暗号化された BLOB データを暗号化解除するためのいくつかのステップが発生します。

  1. クライアント ライブラリによって、暗号化された BLOB データ (暗号化メタデータなど) がストレージ アカウントからダウンロードされます。
  2. 次に、KEK を使用して、ラップされた CEK がラップ解除 (暗号化解除) されます。 このプロセス中、クライアント ライブラリは KEK にアクセスできず、ClientSideEncryptionOptions で指定されたキー ラップ解除アルゴリズムを呼び出すだけです。 RSA キー ペアの秘密キーはキー コンテナーに残っているので、暗号化解除のために、暗号化されたキーが、CEK を含む BLOB メタデータからキー コンテナーに送信されます。
  3. クライアント ライブラリで、CEK を使用して、暗号化された BLOB データが暗号化解除されます。

以前にアップロードされた BLOB をダウンロードして暗号化解除するには、次のコードを追加します。

// Download and decrypt the encrypted contents from the blob
Response<BlobDownloadInfo>  response = await blob.DownloadAsync();
BlobDownloadInfo downloadInfo = response.Value;
Console.WriteLine((await BinaryData.FromStreamAsync(downloadInfo.Content)).ToString());

次のステップ

このチュートリアルでは、.NET クライアント ライブラリを使用して、BLOB のアップロードとダウンロードの操作に対してクライアント側の暗号化を実行する方法について説明しました。

暗号化されたデータをバージョン 2 に移行する手順など、BLOB に使用するクライアント側の暗号化の概要については、「BLOB のクライアント側暗号化」を参照してください。

Azure Key Vault の詳細については、「Azure Key Vault について」を参照してください