Erweiterbarkeit der Kernkryptografie in ASP.NET Core

Warnung

Typen, die eine der folgenden Schnittstellen implementieren, sollten für mehrere Aufrufer threadsicher sein.

IAuthenticatedEncryptor

Die IAuthenticatedEncryptor-Schnittstelle ist der grundlegende Baustein des kryptografischen Subsystems. Im Allgemeinen gibt es einen IAuthenticatedEncryptor pro Schlüssel, und die IAuthenticatedEncryptor-Instanz umschließt alle kryptografischen Schlüsselmaterialien und algorithmischen Informationen, die zum Ausführen kryptografischer Vorgänge erforderlich sind.

Wie der Name schon sagt, ist dieser Typ für die Bereitstellung authentifizierter Verschlüsselungs- und Entschlüsselungsdienste verantwortlich. Er macht die folgenden beiden APIs verfügbar.

  • Decrypt(ArraySegment<byte> ciphertext, ArraySegment<byte> additionalAuthenticatedData) : byte[]

  • Encrypt(ArraySegment<byte> plaintext, ArraySegment<byte> additionalAuthenticatedData) : byte[]

Die Encrypt-Methode gibt ein Blob zurück, das den entschlüsselten Klartext und ein Authentifizierungstag enthält. Das Authentifizierungstag muss die zusätzlichen authentifizierten Daten (Additional Authenticated Data, AAD) umfassen, obwohl sie selbst nicht von der endgültigen Nutzdaten wiederhergestellt werden können. Die Decrypt-Methode überprüft das Authentifizierungstag und gibt die entschlüsselten Nutzdaten zurück. Alle Fehler (mit Ausnahme von „ArgumentNullException“ und ähnlichen Fehlern) sollten zur Klasse „CryptographicException“ homogenisiert werden.

Hinweis

Die IAuthenticatedEncryptor-Instanz selbst muss das Schlüsselmaterial nicht enthalten. Beispielsweise könnte die Implementierung für alle Vorgänge an ein HSM delegiert werden.

Erstellen eines IAuthenticatedEncryptors

Die IAuthenticatedEncryptorFactory-Schnittstelle stellt einen Typ dar, der die Informationen darüber besitzt, wie eine IAuthenticatedEncryptor-Instanz erstellt werden kann. Ihre API lautet wie folgt.

  • CreateEncryptorInstance(IKey key) : IAuthenticatedEncryptor

Für jede IKey-Instanz sollten alle authentifizierten Verschlüsselungen, die von der CreateEncryptorInstance-Methode erstellt wurden, als gleichwertig angesehen werden, wie im folgenden Codebeispiel gezeigt wird.

// 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 (nur ASP.NET Core 2.x)

Die IAuthenticatedEncryptorDescriptor-Schnittstelle stellt einen Typ dar, der sich selbst in XML exportieren kann. Ihre API lautet wie folgt.

  • ExportToXml() : XmlSerializedDescriptorInfo

XML-Serialisierung

Der Hauptunterschied zwischen IAuthenticatedEncryptor und IAuthenticatedEncryptorDescriptor besteht darin, dass der Deskriptor die Informationen darüber besitzt, wie der Verschlüsselungscode erstellt und mit gültigen Argumenten bereitgestellt wird. Stellen Sie sich einen IAuthenticatedEncryptor vor, dessen Implementierung auf SymmetricAlgorithm und KeyedHashAlgorithm basiert. Die Aufgabe des Encryptors besteht darin, diese Typen zu nutzen, er besitzt aber nicht unbedingt die Informationen darüber, wo diese Typen herkamen, sodass er keine brauchbare Beschreibung zur Neuerstellung bei einem Neustart der Anwendung schreiben kann. Der Deskriptor fungiert als darüber liegende höhere Ebene. Da der Deskriptor die Informationen darüber besitzt, wie die Verschlüsselungsinstanz erstellt wird (z. B. wie die erforderlichen Algorithmen erstellt werden), kann er diese Informationen in XML-Form serialisieren, sodass die Verschlüsselungsinstanz nach dem Zurücksetzen der Anwendung neu erstellt werden kann.

Der Deskriptor kann über seine ExportToXml-Routine serialisiert werden. Diese Routine gibt eine XmlSerializedDescriptorInfo zurück, die zwei Eigenschaften enthält: die XElement-Darstellung des Deskriptors und den Typ, der einen IAuthenticatedEncryptorDescriptorDeserializer darstellt. Dieser kann verwendet werden, um diesen Deskriptor unter Berücksichtigung des entsprechenden XElements neu zu erstellen.

Der serialisierte Deskriptor kann vertrauliche Informationen wie kryptografisches Schlüsselmaterial enthalten. Das Datenschutzsystem verfügt über integrierte Unterstützung für die Verschlüsselung von Informationen, bevor sie im Speicher gespeichert werden. Um dies zu nutzen, sollte der Deskriptor das Element, das vertrauliche Informationen enthält, mit dem Attributnamen „requiresEncryption“ (xmlns "<http://schemas.asp.net/2015/03/dataProtection>") und dem Wert „WAHR“ markieren.

Tipp

Es gibt eine Hilfsprogramm-API zum Festlegen dieses Attributs. Rufen Sie die Erweiterungsmethode „XElement.MarkAsRequiresEncryption()“ im Namespace „Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.ConfigurationModel“ auf.

Es kann auch Fälle geben, in denen der serialisierte Deskriptor keine vertraulichen Informationen enthält. Stellen Sie sich erneut einen kryptografischen Schlüssel vor, der in einem HSM gespeichert ist. Der Deskriptor kann das Schlüsselmaterial beim Serialisieren nicht ausschreiben, da das HSM das Material nicht im Klartextformat verfügbar macht. Stattdessen schreibt der Deskriptor möglicherweise die mit einem Schlüssel umschlossene Version des Schlüssels (wenn das HSM den Export auf diese Weise zulässt) oder den eigenen eindeutigen Bezeichner des HSM für den Schlüssel aus.

IAuthenticatedEncryptorDescriptorDeserializer

Die IAuthenticatedEncryptorDescriptorDeserializer-Schnittstelle stellt einen Typ dar, der die Informationen darüber besitzt, wie eine IAuthenticatedEncryptorDescriptor-Instanz aus einem XElement deserialisiert werden kann. Sie macht eine einzelne Methode verfügbar:

  • ImportFromXml(XElement-Element) : IAuthenticatedEncryptorDescriptor

Die ImportFromXml-Methode verwendet das XElement, das von IAuthenticatedEncryptorDescriptor.ExportToXml zurückgegeben wurde, und erstellt ein Äquivalent des ursprünglichen IAuthenticatedEncryptorDescriptor.

Typen, die IAuthenticatedEncryptorDescriptorDeserializer implementieren, sollten über einen der beiden folgenden öffentlichen Konstruktoren verfügen:

  • .ctor(IServiceProvider)

  • .ctor()

Hinweis

Der an den Konstruktor übergebene IServiceProvider kann NULL sein.

Die Factory der obersten Ebene

Die AlgorithmConfiguration-Klasse stellt einen Typ dar, der die Informationen darüber besitzt, wie IAuthenticatedEncryptorDescriptor-Schnittstelle erstellt werden können. Sie macht eine einzelne API verfügbar.

  • CreateNewDescriptor() : IAuthenticatedEncryptorDescriptor

Stellen Sie sich AlgorithmConfiguration als Factory der obersten Ebene vor. Die Konfiguration dient als Vorlage. Sie umschließt algorithmische Informationen (z. B. erzeugt diese Konfiguration Deskriptoren mit einem AES-128-GCM-Hauptschlüssel), ist aber noch keinem bestimmten Schlüssel zugeordnet.

Wenn CreateNewDescriptor aufgerufen wird, wird neues Schlüsselmaterial ausschließlich für diesen Aufruf sowie ein neuer IAuthenticatedEncryptorDescriptor erstellt, der dieses Schlüsselmaterial und die algorithmischen Informationen umschließt, die für die Nutzung des Materials erforderlich sind. Das Schlüsselmaterial könnte in Software erstellt (und im Arbeitsspeicher gespeichert) werden, es könnte in einem HSM erstellt und gespeichert werden usw. Entscheidend ist, dass zwei Aufrufe an CreateNewDescriptor niemals äquivalente IAuthenticatedEncryptorDescriptor-Instanzen erstellen sollten.

Der AlgorithmConfiguration-Typ dient als Einstiegspunkt für Routinen zur Schlüsselerstellung wie automatisches Schlüsselrollen. Um die Implementierung für alle zukünftigen Schlüssel zu ändern, legen Sie die AuthenticatedEncryptorConfiguration-Eigenschaft in KeyManagementOptions fest.