Blob 的用戶端加密
適用於 .NET 的 Azure Blob 儲存體用戶端程式庫支援在上傳至 Azure 儲存體之前將用戶端應用程式內的資料加密,並在下載至用戶端時解密資料。 程式庫也支援與 Azure 金鑰保存庫 整合,以進行儲存體帳戶金鑰管理。
重要
Blob 儲存體同時支援服務端和用戶端加密。 在大部分情況下,Microsoft 建議使用服務端加密功能,以方便用來保護資料。 若要深入了解服務端加密,請參閱待用資料的 Azure 儲存體加密。
如需引導您進行使用用戶端加密和 Azure 金鑰保存庫來加密 Blob 的逐步教學課程,請參閱 在 Microsoft Azure 儲存體中使用 Azure 金鑰保存庫加密和解密 Blob。
關於用戶端加密
Azure Blob 儲存體客戶端連結庫會使用進階加密標準 (AES) 來加密用戶數據。 用戶端程式庫中有兩個可用的用戶端加密版本:
- 第 2 版搭配使用 Galois/Counter Mode (GCM) 模式與 AES。
- 第 1 版搭配使用加密區塊鏈結 (CBC) 模式與 AES。
警告
因為用戶端程式庫 CBC 模式實作的安全性弱點,所以不再建議使用第 1 版的用戶端加密。 如需此安全性弱點的詳細資訊,請參閱Azure 儲存體更新 SDK 中的用戶端加密以解決安全性弱點。 如果您目前使用第 1 版,則建議您更新應用程式以使用第 2 版,並移轉您的資料。 如需進一步指導,請參閱下節:降低應用程式中的安全性弱點。
降低應用程式中的安全性弱點
因為發現 Blob 儲存體用戶端程式庫 CBC 模式實作中的安全性弱點,所以 Microsoft 建議您立即採取下列一或多個動作:
請考慮使用服務端加密功能,而不是用戶端加密。 如需服務端加密功能的詳細資訊,請參閱待用資料的 Azure 儲存體加密。
如果您需要使用用戶端加密,則請將您的應用程式從用戶端加密 v1 移轉至用戶端加密 v2。
下表摘要說明如果您選擇將應用程式遷移至用戶端加密 v2 時應採取的步驟:
用戶端加密狀態 | 建議動作 |
---|---|
應用程式搭配使用用戶端加密與僅支援用戶端加密 v1 的用戶端程式庫版本。 | 更新您的應用程式,以使用支援用戶端加密 v2 的用戶端程式庫版本。 如需支援的版本清單,請參閱用戶端加密的 SDK 支援矩陣。 深入了解... 更新您的程式碼以使用用戶端加密 v2。 深入了解... 下載任何加密的數據以解密,然後使用用戶端加密 v2 重新加密。 深入了解... |
應用程式搭配使用用戶端加密與支援用戶端加密 v2 的用戶端程式庫版本。 | 更新您的程式碼以使用用戶端加密 v2。 深入了解... 下載任何加密的數據以解密,然後使用用戶端加密 v2 重新加密。 深入了解... |
此外,Microsoft 建議您採取下列步驟來協助保護資料:
- 將您的儲存體帳戶設定為使用私人端點,以透過私人連結保護虛擬網路 (VNet) 與儲存體帳戶之間的所有流量。 如需詳細資訊,請參閱針對 Azure 儲存體使用私人端點。
- 僅限制對特定網路的網路存取。
用戶端加密的 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 版和更早版本 |
注意
適用於 12.27.0 版和更新版本的 Java SDK 提供用戶端加密 v2.1。 此版本可讓您設定已驗證加密的區域長度,從 16 個字節到 1 GiB。 如需詳細資訊,請參閱範例:使用用戶端加密 v2 加密和解密 Blob 的 Java 範例。
如果您的應用程式搭配使用用戶端加密與舊版 .NET、Java 或 Python 用戶端程式庫,則您必須先將程式碼升級至支援用戶端加密 v2 的版本。 接下來,您必須使用用戶端加密 v2 來解密並重新加密資料。 如有必要,您可以在移轉程式碼時,使用並存支援用戶端加密 v2 與舊版用戶端程式庫的用戶端程式庫版本。 如需程式碼範例,請參閱範例:使用用戶端加密 v2 加密和解密 Blob。
用戶端加密運作方式
Azure Blob 儲存體用戶端程式庫會使用信封加密來加密和解密用戶端上的資料。 信封加密會使用一或多個額外的金鑰來加密金鑰。
Blob 儲存體用戶端程式庫依賴 Azure Key Vault 來保護用於用戶端加密的金鑰。 如需 Azure Key Vault 的詳細資訊,請參閱什麼是 Azure Key Vault。
透過信封技術進行加密和解密
透過信封技術的加密運作如下:
Azure 儲存體用戶端程式庫會產生內容加密金鑰 (CEK),這是使用一次的對稱金鑰。
使用 CEK 來加密使用者資料。
然後使用金鑰加密金鑰 (KEK) 包裝 (加密) CEK。 KEK 是以金鑰識別碼予以識別,而且可以是非對稱金鑰組或對稱金鑰。 您可以在本機管理 KEK,或將其儲存至 Azure Key Vault。
Azure 儲存體用戶端程式庫本身永遠無法存取 KEK。 程式庫會叫用金鑰保存庫所提供的金鑰包裝演算法。 如有需要,使用者可以選擇使用自訂提供者來包裝/取消包裝金鑰。
接著會將已加密的資料上傳至 Azure Blob 儲存體。 包裝的金鑰與一些額外的加密中繼資料會儲存為 Blob 上的中繼資料。
透過信封技術的解密運作如下:
- Azure 儲存體用戶端程式庫假設使用者在本機或 Azure Key Vault 中管理 KEK。 使用者不必知道用於加密的特定金鑰。 相反地,可以設定並使用金鑰解析程式,將不同的金鑰識別碼解析成金鑰。
- 用戶端程式庫會下載加密的資料,以及任何儲存在 Azure 儲存體中的加密資料。
- 包裝的 CEK 接著會使用 KEK 解除包裝 (解密)。 用戶端程式庫在此程序期間無法存取 KEK,而是只會叫用 Azure Key Vault 或其他金鑰存放區的解除包裝演算法。
- 用戶端程式庫會使用 CEK 來解密加密的使用者資料。
Blob 上傳/下載時的加密/解密
Blob 儲存體用戶端程式庫僅支援上傳時加密整個 Blob。 針對下載,則皆支援完整與範圍下載。 用戶端加密 v2 會將數據區塊化為 4 MiB 緩衝的已驗證加密區塊,而該區塊只能轉換整個。 若要調整區塊大小,請確定您使用的是支援用戶端加密 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 的內容。 呼叫設定 Blob 中繼資料作業時一律會取代所有 Blob 中繼資料。
讀取或寫入已加密的 Blob 時,使用整個 Blob 上傳命令 (例如放置 Blob) 和範圍/整個 Blob 下載命令(例如「取得 Blob」)。 避免寫入使用通訊協定作業的已加密 Blob,例如 放置區塊、放置區塊清單、放置頁面或附加區塊。 在已加密的 Blob 上呼叫這些作業可能會將其損毀,並使其無法進行讀取。
範例:使用用戶端加密 v2 加密和解密 Blob
本節中的程式碼範例顯示如何使用用戶端加密 v2 來加密和解密 Blob。
重要
如果您有先前使用用戶端加密 v1 加密的數據,則必須解密該數據,並使用用戶端加密 v2 重新加密數據。 請參閱下方的用戶端程式庫指導和範例。
若要從 .NET 程式碼使用用戶端加密,請參考 Blob 儲存體用戶端程式庫。 請確定您使用的是 12.13.0 版或更新版本。 如果您需要從 11.x 版移轉至 12.13.0 版,請參閱移轉指南。
Azure Key Vault 整合進行用戶端加密需要兩個額外的套件:
Azure.Core 套件提供
IKeyEncryptionKey
和IKeyEncryptionKeyResolver
介面。 .NET 的 Blob 儲存體用戶端程式庫已將此組件定義為相依性。Azure.Security.KeyVault.Keys 套件 (4.x 版和更新版本) 提供 Key Vault REST 用戶端以及與用戶端加密搭配使用的密碼編譯用戶端。 如果您使用 Azure 金鑰保存庫 作為金鑰存放區,請確定專案中會參考此套件。
Azure 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 記憶體。
用戶端加密和效能
請記住,加密您的儲存體資料會造成額外的效能負擔。 當您在應用程式中使用用戶端加密時,用戶端程式庫必須安全地產生 CEK 和 IV、加密內容本身、與您選擇的金鑰存放區通訊以進行金鑰信封處理,以及格式化和上傳其他中繼資料。 這個額外負荷會因所加密資料的數量而不同。 我們建議客戶一定要在開發期間測試其應用程式的效能。