BLOB のクライアント側暗号化
.NET 用 Azure Blob Storage クライアント ライブラリ は、Azure Storage にアップロードする前にクライアント アプリケーション内のデータを暗号化し、クライアントにダウンロードするときにデータの暗号化を解除する作業を支援します。 また、このライブラリは Azure Key Vault の統合にも役立ち、ストレージ アカウント キー管理に利用することもできます。
重要
Blob Storage では、サービス側とクライアント側の両方の暗号化がサポートされています。 ほとんどのシナリオでは、データの保護で使いやすいようにサービス側の暗号化機能を使用することをお勧めします。 サービス側暗号化の詳細については、「保存データに対する Azure Storage 暗号化」をご覧ください。
クライアント側の暗号化と Azure Key Vault を使用して BLOB を暗号化するプロセスを紹介するステップ バイ ステップ チュートリアルについては、「 チュートリアル: Azure Key Vault を使用した Microsoft Azure Storage 内の BLOB の暗号化と復号化」をご覧ください。
クライアント側の暗号化について
Azure Blob Storage クライアント ライブラリは AES を使用して、ユーザー データを暗号化します。 クライアント ライブラリでは、次の 2 つのバージョンのクライアント側暗号化を使用できます。
- バージョン 2 では、AES で Galois/Counter Mode (GCM) モードが使用されます。
- バージョン 1 では、AES で暗号ブロック チェーン (CBC) モードが使用されます。
警告
クライアント ライブラリでの CBC モードの実装を原因とするセキュリティの脆弱性により、クライアント側暗号化のバージョン 1 の使用は推奨されなくなりました。 このセキュリティ脆弱性の詳細については、セキュリティの脆弱性に対処するために Azure Storage で行われた SDK のクライアント側暗号化の更新に関するページを参照してください。 現在バージョン 1 を使用している場合は、バージョン 2 を使用するようにアプリケーションを更新し、データを移行することをお勧めします。 次の「アプリケーションのセキュリティの脆弱性を軽減する」セクションで、詳細なガイダンスについてご覧ください。
アプリケーションのセキュリティの脆弱性を軽減する
Blob Storage クライアント ライブラリの CBC モードの実装においてセキュリティの脆弱性が検出されたため、直ちに次の 1 つ以上の措置をとることをお勧めします。
クライアント側暗号化でなく、サービス側暗号化機能を使用することを検討してください。 サービス側暗号化機能の詳細については、「保存データに対する Azure Storage 暗号化」をご覧ください。
クライアント側暗号化を使用する必要がある場合は、クライアント側暗号化 v1 からクライアント側暗号化 v2 にアプリケーションを移行してください。
次の表は、アプリケーションをクライアント側暗号化 v2 に移行する場合に実行する必要がある手順をまとめたものです。
クライアント側暗号化の状態 | 推奨アクション |
---|---|
アプリケーションが使用しているクライアント側暗号化で、クライアント ライブラリのバージョンがクライアント側暗号化 v1 のみをサポートしている。 | クライアント側暗号化 v2 がサポートされているクライアント ライブラリのバージョンを使用するようにアプリケーションを更新します。 サポートされているバージョンの一覧については、「クライアント側暗号化の SDK サポート マトリックス」をご覧ください。 詳細情報 クライアント側暗号化 v2 を使用するようにコードを更新します。 詳細情報 暗号化されたデータをダウンロードして暗号化を解除し、クライアント側暗号化 v2 で再暗号化します。 詳細情報 |
アプリケーションが使用しているクライアント側暗号化のクライアント ライブラリのバージョンがクライアント側暗号化 v2 をサポートしている。 | クライアント側暗号化 v2 を使用するようにコードを更新します。 詳細情報 暗号化されたデータをダウンロードして暗号化を解除し、クライアント側暗号化 v2 で再暗号化します。 詳細情報 |
さらに、次の手順を行なってデータをセキュリティ保護することをお勧めします。
- プライベート エンドポイントを使用して、プライベート リンク上の仮想ネットワーク (VNet) とストレージ アカウントの間のすべてのトラフィックをセキュリティ保護するようストレージ アカウントを構成します。 詳細については、「Azure Storage のプライベート エンドポイントを使用する」を参照してください。
- ネットワーク アクセスを特定のネットワークだけに制限します。
クライアント側暗号化の SDK サポート マトリックス
次の表は、どのバージョンの .NET、Java、Python 用クライアント ライブラリが、どのバージョンのクライアント側暗号化をサポートするかを示しています。
.NET | Java | Python | |
---|---|---|---|
クライアント側暗号化 v2 および v1 | バージョン 12.13.0 以降 | バージョン 12.18.0 以降 | バージョン 12.13.0 以降 |
クライアント側暗号化 v1 のみ | バージョン 12.12.0 以前 | バージョン 12.17.0 以前 | バージョン 12.12.0 以前 |
アプリケーションが以前のバージョンの .NET、Java、または Python クライアント ライブラリでクライアント側暗号化を使用している場合は、最初に、クライアント側暗号化 v2 をサポートするバージョンにコードをアップグレードする必要があります。 次に、クライアント側暗号化 v2 を使用してデータを復号化して再暗号化する必要があります。 必要であれば、コードの移行中に、クライアント側暗号化 v2 をサポートするバージョンのクライアント ライブラリを、以前のバージョンのクライアント ライブラリと並行して使用することができます。 コード例については、「例: クライアント側暗号化 v2 を使用した BLOB の暗号化と復号化」を参照してください。
クライアント側暗号化の仕組み
Azure Blob Storage クライアント ライブラリでは、エンベロープ暗号化を使用して、クライアント側のデータを暗号化および復号化します。 エンベロープ暗号化では、キーの暗号化を 1 つ以上の追加キーを使用して行います。
Blob Storage クライアント ライブラリは、クライアント側暗号化に使用されるキーを保護するために Azure Key Vault に依存しています。 Azure Key Vault の詳細については、「Azure Key Vault とは」をご覧ください。
エンベロープ手法による暗号化と復号化
エンベロープ手法による暗号化は、次のように機能します。
Azure Storage クライアント ライブラリは、1 回使用の対称キーであるコンテンツ暗号化キー (CEK) を生成します。
ユーザー データが CEK を使用して暗号化されます。
CEK は、キー暗号化キー (KEK) を使用してラップ (暗号化) されます。 KEK は、キー識別子によって識別され、非対称キー ペアまたは対称キーのどちらにでもできます。 CEK はローカルで管理するか、Azure Key Vault に保管します。
Azure Storage クライアント ライブラリ自体が KEK にアクセスすることはありません。 ライブラリは、Key Vault によって提供されるキー ラップ アルゴリズムを呼び出すだけです。 ユーザーは、必要な場合は、キー ラップ/ラップ解除にカスタム プロバイダーを使用できます。
その後、暗号化されたデータは Azure Blob Storage にアップロードされます。 ラップされたキーといくつかの追加の暗号化メタデータは、BLOB にメタデータとして保管されます。
エンベロープ手法による復号化は、次のように機能します。
- Azure Storage クライアント ライブラリでは、ユーザーが KEK をローカルまたは Azure Key Vault のいずれかで管理することを前提としています。 ユーザーは、暗号化に使用された特定のキーを把握しておく必要はありません。 代わりに、さまざまなキー識別子をキーに解決する Key Resolver を設定、使用できます。
- クライアント ライブラリは、暗号化されたデータおよび Azure Storage に格納されている暗号化に関する情報 (ある場合) をダウンロードします。
- ラップされた CEK は、KEK を使用してラップ解除 (復号化) されます。 クライアント ライブラリはこのプロセス中に KEK にアクセスできませんが、Azure Key Vault または他のキー ストアのラップ解除アルゴリズムのみを呼び出します。
- クライアント ライブラリは、CEK を使用して暗号化されたユーザー データを復号化します。
BLOB のアップロード/ダウンロードでの暗号化/復号化
Blob Storage クライアント ライブラリでは、アップロード時にのみ BLOB 全体の暗号化がサポートされます。 ダウンロードについては、完全ダウンロードと一部の範囲のダウンロードの両方がサポートされています。 クライアント側の暗号化 v2 は、データを 4 MB のバッファー認証された暗号化ブロックにチャンクすることで、全体の変換しかできないようにします。 チャンク サイズを調整するには、クライアント側の暗号化 v2.1 をサポートする最新バージョンの SDK を使用していることを確認します。 リージョンの長さは、16 バイトから 1 GiB まで構成できます。
暗号化中、クライアント ライブラリは 16 バイトのランダム初期化ベクター (IV) と 32 バイトのランダムな CEK を生成し、この情報を使用して BLOB データのエンベロープ暗号化を実行します。 ラップされた CEK と一部の追加暗号化メタデータが、暗号化された BLOB と共に、BLOB メタデータとして格納されます。
クライアントが BLOB 全体をダウンロードするとき、ラップされた CEK はラップ解除されて、復号化されたデータをクライアントに返すために IV と共に使用されます。
暗号化された BLOB での任意の範囲のダウンロードでは、ユーザーが指定した範囲が調整されます。これは、少量の追加データを取得して、要求された範囲を正常に復号化するためです。
このスキームを使用して、すべての BLOB 型 (ブロック BLOB、ページ BLOB、および追加 BLOB) を暗号化/復号化できます。
警告
BLOB のメタデータを編集またはアップロードする場合は、暗号化メタデータが保持されるようにする必要があります。 暗号化メタデータも保持せずに新しいメタデータをアップロードすると、ラップされた CEK、IV、および他のメタデータが失われ、BLOB の内容を取得できなくなります。 Set Blob Metadata 操作を呼び出すと、常にすべての BLOB メタデータが置き換えられます。
暗号化された BLOB を読み書きするときは、完全 BLOB アップロード コマンド (Put Blob) と範囲/完全 BLOB ダウンロード コマンド (Get Blob) を使用してください。 Put Block、Put Block List、Put Page、または Append Block などのプロトコル操作を使用して暗号化された BLOB に書き込まないでください。 暗号化された BLOB でこれらの操作を呼び出すと、BLOB が壊れて読み取り不能になる可能性があります。
例: クライアント側暗号化 v2 を使用した BLOB の暗号化と復号化
このセクションのコード例では、クライアント側暗号化 v2 を使用して BLOB を暗号化および復号化する方法を示します。
重要
以前にクライアント側暗号化 v1 で暗号化されたデータがある場合は、そのデータを復号化してクライアント側暗号化 v2 で再暗号化する必要があります。 以下のクライアント ライブラリのガイダンスとサンプルを参照してください。
クライアント側暗号化を .NET コードから使用するには、「Blob Storage クライアント ライブラリ」を参照してください。 バージョン 12.13.0 以降を使用していることを確認します。 バージョン 11.x からバージョン 12.13.0 に移行する必要がある場合は、「移行ガイド」をご覧ください。
クライアント側暗号化用の Azure Key Vault 統合には、次の 2 つの追加パッケージが必要です。
Azure.Core パッケージには、
IKeyEncryptionKey
およびIKeyEncryptionKeyResolver
インターフェイスが用意されています。 .NET 用 Blob Storage クライアント ライブラリでは、このアセンブリが既に依存関係として定義されています。Azure.Security.KeyVault.Keys パッケージ (バージョン 4.x 以降) には、Key Vault REST クライアントと、クライアント側暗号化で使用される暗号化クライアントが用意されています。 Azure Key Vault をキー ストアとして使用している場合は、このパッケージがプロジェクトで参照されていることを確認する必要があります。
Azure Key Vault は値の高いマスター キー向けで、Key Vault ごとのスロットルの上限がこの設計を反映しています。 Azure.Security.KeyVault.Keys のバージョン 4.1.0 以降、
IKeyEncryptionKeyResolver
インターフェイスではキー キャッシュがサポートされていません。 スロットルのためにキャッシュする必要がある場合は、こちらのサンプルに従ってキャッシュ層をAzure.Security.KeyVault.Keys.Cryptography.KeyResolver
インスタンスに挿入できます。
開発者がキー、キー リゾルバー、またはキーとキー リゾルバーの両方を提供できます。 キーを識別するために使用するキー識別子は、CEK をラップ/ラップ解除するためのロジックを指定します。 キー リゾルバーを使用して復号化プロセス中にキーを解決します。 キー リゾルバーは、指定されたキー識別子のキーを返す解決方法を定義します。 リゾルバーは、複数の場所で管理されている複数のキーの中から選択するための機能を提供します。
暗号化では、キーは常に使用され、キーがないとエラーが発生します。
復号化では、キーが指定されてその識別子が必要なキー識別子と一致する場合、そのキーが復号化に使用されます。 それ以外の場合、クライアント ライブラリはリゾルバーの呼び出しを試みます。 リゾルバーが指定されていない場合、クライアント ライブラリはエラーをスローします。 リゾルバーが指定されている場合、キーリゾルバーは呼び出されてキーを取得します。 リゾルバーが指定されていても、キー識別子のマッピングがない場合、クライアント ライブラリはエラーをスローします。
クライアント側暗号化を使用するには、ClientSideEncryptionOptions オブジェクトを作成し、それをクライアント作成時に SpecializedBlobClientOptions で設定します。 API ごとに暗号化オプションを設定することはできません。 その他の操作はすべて、クライアント ライブラリが内部的に処理します。
// Your key and key resolver instances, either through Azure Key Vault SDK or an external implementation.
IKeyEncryptionKey key;
IKeyEncryptionKeyResolver keyResolver;
// Create the encryption options to be used for upload and download.
ClientSideEncryptionOptions encryptionOptions = new ClientSideEncryptionOptions(ClientSideEncryptionVersion.V2_0)
{
KeyEncryptionKey = key,
KeyResolver = keyResolver,
// String value that the client library will use when calling IKeyEncryptionKey.WrapKey()
KeyWrapAlgorithm = "some algorithm name"
};
// Set the encryption options on the client options.
BlobClientOptions options = new SpecializedBlobClientOptions() { ClientSideEncryption = encryptionOptions };
// Create blob client with client-side encryption enabled.
// Client-side encryption options are passed from service clients to container clients,
// and from container clients to blob clients.
// 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.
BlobClient blob = new BlobServiceClient
(new Uri($"https://{accountName}.blob.core.windows.net"), new DefaultAzureCredential(), options).GetBlobContainerClient("my-container").GetBlobClient("myBlob");
// Upload the encrypted contents to the blob.
blob.Upload(stream);
// Download and decrypt the encrypted contents from the blob.
MemoryStream outputStream = new MemoryStream();
blob.DownloadTo(outputStream);
暗号化オプションを、BlobClientOptions オブジェクトを受け入れる BlobServiceClient、BlobContainerClient、または BlobClient コンストラクターに適用できます。
BlobClient オブジェクトが既にコードに存在するがクライアント側暗号化オプションがない場合は、指定された ClientSideEncryptionOptions を使用してそのオブジェクトのコピーを作成する拡張メソッドを使用できます。 この拡張メソッドにより、新しい BlobClient オブジェクトをゼロから構築するオーバーヘッドが回避されます。
using Azure.Storage.Blobs.Specialized;
// An existing BlobClient instance and encryption options.
BlobClient plaintextBlob;
ClientSideEncryptionOptions encryptionOptions;
// Get a copy of the blob that uses client-side encryption.
BlobClient clientSideEncryptionBlob = plaintextBlob.WithClientSideEncryptionOptions(encryptionOptions);
クライアント側暗号化 v2 を使用するようにコードを更新した後、「クライアント側暗号化 v2 を使用して以前に暗号化されたデータを再暗号化する」の説明に従って、暗号化 された既存のデータを暗号化解除して再暗号化してください。
クライアント側暗号化 v2 を使用して以前に暗号化されたデータを再暗号化する
以前にクライアント側暗号化 v1 で暗号化されていたデータを復号化してからクライアント側暗号化 v2 で再暗号化して、セキュリティの脆弱性を軽減する必要があります。 復号化でデータをダウンロードする必要があり、再暗号化でそれを Blob Storage へ再アップロードする必要があります。
クライアント側暗号化 v1 から v2 にデータを移行する方法と、.NET でクライアント側暗号化 v2 を使用してデータを暗号化する方法を示すサンプル プロジェクトについては、「暗号化移行のサンプル プロジェクト」を参照してください。
クライアント側暗号化とパフォーマンス
ストレージ データを暗号化すると、パフォーマンスのオーバーヘッドが増えることを忘れないでください。 アプリケーションでクライアント側暗号化を使用するとき、クライアント ライブラリは、CEK と IV を安全に生成し、コンテンツ自体を暗号化し、選択したキーを包み込むためのキーストアと通信し、追加のメタデータを書式設定してアップロードする必要があります。 このオーバーヘッドは、暗号化されるデータの量によって変わります。 開発中に、アプリケーションのパフォーマンスを常にテストすることをお勧めします。