ASP.NET Core 中的核心加密擴充性
警告
多個呼叫端的類型應是安全執行緒,其類型會實作下列任何介面。
IAuthenticatedEncryptor
IAuthenticatedEncryptor 介面是加密子系統的基本建置區塊。 每個金鑰通常會有一個 IAuthenticatedEncryptor,而 IAuthenticatedEncryptor 執行個體會包裝所有加密金鑰資料和演算法資訊,在執行加密作業會需要使用這些資訊。
如其名稱所示,此類型負責提供已驗證的加密和解密服務。 其會公開下列兩個 API。
Decrypt(ArraySegment<byte> ciphertext, ArraySegment<byte> additionalAuthenticatedData) : byte[]
Encrypt(ArraySegment<byte> plaintext, ArraySegment<byte> additionalAuthenticatedData) : byte[]
加密方法會傳回 Blob,其中包含加密的純文字和驗證標籤。 驗證標籤必須包含額外的已驗證資料 (AAD),不過 AAD 本身不一定可從最終承載復原。 解密方法會對驗證標籤進行驗證,並傳回已解碼的承載。 所有失敗 (除了 ArgumentNullException 和類似的失敗) 都應該同質化為 CryptographicException。
注意
IAuthenticatedEncryptor 執行個體本身實際上不需要包含金鑰資料。 例如,實作可以委派給所有作業的 HSM。
如何建立 IAuthenticatedEncryptor
IAuthenticatedEncryptorFactory 介面代表一種類型,該類型知道如何建立 IAuthenticatedEncryptor 執行個體。 其 API 如下所示。
- CreateEncryptorInstance(IKey 金鑰):IAuthenticatedEncryptor
如下列程式碼範例所示,針對任何指定的 IKey 執行個體,都應將其 CreateEncryptorInstance 方法所建立的任何已驗證加密程式視為對等項目。
// we have an IAuthenticatedEncryptorFactory instance and an IKey instance
IAuthenticatedEncryptorFactory factory = ...;
IKey key = ...;
// get an encryptor instance and perform an authenticated encryption operation
ArraySegment<byte> plaintext = new ArraySegment<byte>(Encoding.UTF8.GetBytes("plaintext"));
ArraySegment<byte> aad = new ArraySegment<byte>(Encoding.UTF8.GetBytes("AAD"));
var encryptor1 = factory.CreateEncryptorInstance(key);
byte[] ciphertext = encryptor1.Encrypt(plaintext, aad);
// get another encryptor instance and perform an authenticated decryption operation
var encryptor2 = factory.CreateEncryptorInstance(key);
byte[] roundTripped = encryptor2.Decrypt(new ArraySegment<byte>(ciphertext), aad);
// the 'roundTripped' and 'plaintext' buffers should be equivalent
IAuthenticatedEncryptorDescriptor (僅限 ASP.NET Core 2.x)
IAuthenticatedEncryptorDescriptor 介面代表一種類型,該類型知道如何將本身匯出為 XML。 其 API 如下所示。
- ExportToXml() : XmlSerializedDescriptorInfo
XML 序列化
IAuthenticatedEncryptor 與 IAuthenticatedEncryptorDescriptor 之間的主要差異在於,描述項知道如何建立加密程式,並為其提供有效的引數。 請考量 IAuthenticatedEncryptor,其實作有賴於 SymmetricAlgorithm 和 KeyedHashAlgorithm。 加密程式的作業是取用這些類型,但其不一定知道這些類型的來源,因此其無法真正寫出適當描述,以說明如何在應用程式重新啟動時自我重建。 在此基礎上,描述項會發揮較高層級的作用。 由於描述項知道如何建立加密程式執行個體 (例如,其知道如何建立必要的演算法),所以其會以 XML 形式序列化該知識,以便在應用程式重設之後重新建立加密程式執行個體。
可以透過描述項的 ExportToXml 常式對其進行序列化。 此常式會傳回 XmlSerializedDescriptorInfo,其中包含兩個屬性:描述項的 XElement 表示法,以及代表 IAuthenticatedEncryptorDescriptorDeserializer 的類型,這兩個屬性可用來根據對應的 XElement 恢復此描述項。
序列化描述項可能包含敏感性資訊,例如加密金鑰資料。 資料保護系統具有內建的支援,可在將資訊保存至儲存體前加密資訊。 若要利用這項功能,描述項應該以屬性名稱「requiresEncryption」(xmlns "<http://schemas.asp.net/2015/03/dataProtection>"
),值「true」,標記包含敏感性資訊的元素。
提示
有可設定此屬性的協助程式 API。 呼叫位於命名空間 Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.ConfigurationModel 的擴充方法 XElement.MarkAsRequiresEncryption()。
也可能會有序列化描述項不包含敏感性資訊的案例。 再次考量在 HSM 中儲存的加密金鑰案例。 當序列化描述項本身時,描述項無法寫出金鑰資料,因為 HSM 不會以純文字形式公開資料。 相反地,描述項可能會寫出金鑰包裝的金鑰版本 (如果 HSM 允許以這種方式匯出),或是 HSM 本身的金鑰唯一識別碼。
IAuthenticatedEncryptorDescriptorDeserializer
IAuthenticatedEncryptorDescriptorDeserializer 介面代表一種類型,該類型知道如何從 XElement 還原序列化 IAuthenticatedEncryptorDescriptor 執行個體。 其會公開單一方法:
- ImportFromXml (XElement 元素):IAuthenticatedEncryptorDescriptor
ImportFromXml 方法會採用 IAuthenticatedEncryptorDescriptor.ExportToXml 所傳回的 XElement,並建立原始 IAuthenticatedEncryptorDescriptor 的對等項目。
實作 IAuthenticatedEncryptorDescriptorDeserializer 的類型應該有下列兩個公用建構函式之一:
.ctor(IServiceProvider)
.ctor()
注意
傳遞至建構函式的 IServiceProvider 可能是 Null。
最上層中心
AlgorithmConfiguration 類別代表一種類型,該類型知道如何建立 IAuthenticatedEncryptorDescriptor 執行個體。 其會公開單一 API。
- CreateNewDescriptor():IAuthenticatedEncryptorDescriptor
將 AlgorithmConfiguration 視為最上層的中心。 此設定可作為範本。 其會包裝演算法資訊 (例如,此設定會產生具有 AES-128-GCM 主要金鑰的描述項),但其尚未與特定金鑰相關聯。
呼叫 CreateNewDescriptor 時,只會針對此呼叫建立新的金鑰資料,並產生新的 IAuthenticatedEncryptorDescriptor,其會包裝此金鑰資料,以及取用資料所需的演算法資訊。 您可以在軟體中建立金鑰資料 (並保留在記憶體中),也可以在 HSM 中建立並保留該金鑰資料,依此類推。 關鍵是,對 CreateNewDescriptor 的任兩個呼叫絕對不應建立對等的 IAuthenticatedEncryptorDescriptor 執行個體。
AlgorithmConfiguration 類型可作為金鑰建立常式的進入點,例如自動金鑰輪替。 若要變更所有未來金鑰的實作,請在 KeyManagementOptions 中設定 AuthenticatedEncryptorConfiguration 屬性。