Rozszerzalność kryptografii podstawowej w ASP.NET Core
Ostrzeżenie
Typy implementujące dowolny z następujących interfejsów powinny być bezpieczne wątkowo dla wielu wywołujących.
IAuthenticatedEncryptor
Interfejs IAuthenticatedEncryptor to podstawowy blok konstrukcyjny podsystemu kryptograficznego. Zazwyczaj istnieje jeden element IAuthenticatedEncryptor na klucz, a wystąpienie IAuthenticatedEncryptor opakowuje wszystkie materiały klucza kryptograficznego i informacje algorytmiczne niezbędne do wykonywania operacji kryptograficznych.
Jak sugeruje jego nazwa, typ jest odpowiedzialny za dostarczanie uwierzytelnionych usług szyfrowania i odszyfrowywania. Uwidacznia następujące dwa interfejsy API.
Decrypt(ArraySegment<byte> ciphertext, ArraySegment<byte> additionalAuthenticatedData) : byte[]
Encrypt(ArraySegment<byte> plaintext, ArraySegment<byte> additionalAuthenticatedData) : byte[]
Metoda Encrypt zwraca obiekt blob zawierający zaszyfrowany zwykły tekst i tag uwierzytelniania. Tag uwierzytelniania musi obejmować dodatkowe uwierzytelnione dane (AAD), chociaż sama usługa AAD nie musi być odzyskiwalna z końcowego ładunku. Metoda Decrypt weryfikuje tag uwierzytelniania i zwraca rozszyfrowany ładunek. Wszystkie błędy (z wyjątkiem ArgumentNullException i podobne) powinny być homogenizowane na Wartość CryptographicException.
Uwaga
Samo wystąpienie IAuthenticatedEncryptor nie musi zawierać materiału klucza. Na przykład implementacja może delegować do modułu HSM dla wszystkich operacji.
Jak utworzyć element IAuthenticatedEncryptor
Interfejs IAuthenticatedEncryptorFactory reprezentuje typ, który wie, jak utworzyć wystąpienie IAuthenticatedEncryptor . Jego interfejs API jest następujący.
- CreateEncryptorInstance(klucz IKey): IAuthenticatedEncryptor
W przypadku dowolnego wystąpienia IKey wszystkie uwierzytelnione szyfratory utworzone przez metodę CreateEncryptorInstance powinny być traktowane jako równoważne, jak w poniższym przykładzie kodu.
// 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 (tylko ASP.NET Core 2.x)
Interfejs IAuthenticatedEncryptorDescriptor reprezentuje typ, który wie, jak wyeksportować się do kodu XML. Jego interfejs API jest następujący.
- ExportToXml() : XmlSerializedDescriptorInfo
Serializacji XML
Podstawową różnicą między elementami IAuthenticatedEncryptor i IAuthenticatedEncryptorDescriptor jest to, że deskryptor wie, jak utworzyć program szyfrujący i podać go prawidłowymi argumentami. Rozważ element IAuthenticatedEncryptor, którego implementacja opiera się na SymmetricAlgorithm i KeyedHashAlgorithm. Zadanie szyfrora polega na użyciu tych typów, ale niekoniecznie wie, skąd pochodzą te typy, więc nie może on naprawdę napisać prawidłowy opis sposobu ponownego utworzenia aplikacji, jeśli aplikacja zostanie uruchomiona ponownie. Deskryptor działa jako wyższy poziom na tym poziomie. Ponieważ deskryptor wie, jak utworzyć wystąpienie szyfrowania (na przykład wie, jak utworzyć wymagane algorytmy), może serializować wiedzę w postaci XML, aby można było odtworzyć wystąpienie szyfrujące po zresetowaniu aplikacji.
Deskryptor można serializować za pomocą procedury ExportToXml. Ta rutyna zwraca element XmlSerializedDescriptorInfo zawierający dwie właściwości: reprezentację XElement deskryptora i typ, który reprezentuje element IAuthenticatedEncryptorDescriptorDeserializer , który może służyć do wskrzeszania tego deskryptora, biorąc pod uwagę odpowiedni element XElement.
Serializowany deskryptor może zawierać poufne informacje, takie jak materiał klucza kryptograficznego. System ochrony danych ma wbudowaną obsługę szyfrowania informacji przed utrwalone w magazynie. Aby to wykorzystać, deskryptor powinien oznaczyć element zawierający poufne informacje o nazwie atrybutu "requiresEncryption" (xmlns "<http://schemas.asp.net/2015/03/dataProtection>"
), wartość "true".
Napiwek
Istnieje interfejs API pomocnika służący do ustawiania tego atrybutu. Wywołaj metodę rozszerzenia XElement.MarkAsRequiresEncryption() znajdującą się w przestrzeni nazw Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.ConfigurationModel.
Mogą również wystąpić przypadki, w których deskryptor serializowany nie zawiera poufnych informacji. Rozważ ponownie przypadek klucza kryptograficznego przechowywanego w module HSM. Deskryptor nie może wypisać materiału klucza podczas serializacji, ponieważ moduł HSM nie uwidacznia materiału w postaci zwykłego tekstu. Zamiast tego deskryptor może zapisać wersję klucza opakowaną kluczem (jeśli moduł HSM zezwala na eksportowanie w ten sposób) lub własny unikatowy identyfikator modułu HSM dla klucza.
IAuthenticatedEncryptorDescriptorDeserializer
Interfejs IAuthenticatedEncryptorDescriptorDeserializer reprezentuje typ, który wie, jak deserializować wystąpienie IAuthenticatedEncryptorDescriptor z elementu XElement. Uwidacznia jedną metodę:
- ImportFromXml(element XElement): IAuthenticatedEncryptorDescriptor
Metoda ImportFromXml przyjmuje element XElement zwrócony przez element IAuthenticatedEncryptorDescriptor.ExportToXml i tworzy odpowiednik oryginalnego elementu IAuthenticatedEncryptorDescriptor.
Typy implementowane IAuthenticatedEncryptorDescriptorDeserializer powinny mieć jeden z następujących dwóch konstruktorów publicznych:
.ctor(IServiceProvider)
.ctor()
Uwaga
Element IServiceProvider przekazany do konstruktora może mieć wartość null.
Fabryka najwyższego poziomu
Klasa AlgorithmConfiguration reprezentuje typ, który wie, jak utworzyć wystąpienia IAuthenticatedEncryptorDescriptor . Uwidacznia pojedynczy interfejs API.
- CreateNewDescriptor() : IAuthenticatedEncryptorDescriptor
Funkcja AlgorithmConfiguration jest fabryką najwyższego poziomu. Konfiguracja służy jako szablon. Opakowuje on informacje algorytmiczne (na przykład ta konfiguracja generuje deskryptory z kluczem głównym AES-128-GCM), ale nie jest jeszcze skojarzony z określonym kluczem.
Po wywołaniu metody CreateNewDescriptor tworzony jest świeży materiał klucza wyłącznie dla tego wywołania, a nowy element IAuthenticatedEncryptorDescriptor jest tworzony, który opakowuje ten materiał klucza i informacje algorytmiczne wymagane do korzystania z materiału. Materiał klucza można utworzyć w oprogramowaniu (i przechowywać w pamięci), można go utworzyć i przechowywać w module HSM itd. Kluczowym punktem jest to, że wszystkie dwa wywołania metody CreateNewDescriptor nigdy nie powinny tworzyć równoważnych wystąpień IAuthenticatedEncryptorDescriptor.
Typ AlgorithmConfiguration służy jako punkt wejścia dla procedur tworzenia kluczy, takich jak automatyczne kroczenie klucza. Aby zmienić implementację wszystkich przyszłych kluczy, ustaw właściwość AuthenticatedEncryptorConfiguration w polu KeyManagementOptions.