Teilen über


Konfigurieren des Schutzes von Daten in ASP.NET Core

Wenn das Datenschutzsystem initialisiert wird, werden Standardeinstellungen basierend auf der Betriebsumgebung angewandt. Diese Einstellungen eignen sich für Apps, die auf einem einzelnen Computer ausgeführt werden. Es gibt jedoch Fälle, in denen Entwickler*innen die Standardeinstellungen ändern möchten:

  • Die App ist auf mehrere Computer verteilt.
  • Aus Compliance-Gründen.

Für diese Szenarien bietet das Datenschutzsystem eine umfangreiche Konfigurations-API.

Warning

Ähnlich wie bei Konfigurationsdateien sollte der Schlüsselring für den Datenschutz mit entsprechenden Berechtigungen geschützt werden. Sie können ruhende Schlüssel verschlüsseln, wodurch jedoch nicht verhindert wird, dass Cyberangriffe neue Schlüssel erstellen. Folglich wird die Sicherheit Ihrer App beeinträchtigt. Der mit Datenschutz konfigurierte Speicherort sollte auf die App selbst beschränkt sein, ähnlich wie beim Schutz von Konfigurationsdateien. Wenn Sie sich beispielsweise dafür entscheiden, Ihren Schlüsselring auf dem Datenträger zu speichern, verwenden Sie Dateisystemberechtigungen. Stellen Sie sicher, dass nur die Identität, unter der Ihre Web-App ausgeführt wird, Lese-, Schreib- und Zugriff auf dieses Verzeichnis hat. Wenn Sie Azure Blob Storage verwenden, sollte nur die Web-App die Möglichkeit haben, Einträge im Blobspeicher usw. zu lesen oder zu schreiben oder neue Einträge zu erstellen.

Die Erweiterungsmethode AddDataProtection gibt einen IDataProtectionBuilder zurück. IDataProtectionBuilder macht Erweiterungsmethoden verfügbar, die Sie verketten können, um Datenschutzoptionen zu konfigurieren.

Note

Dieser Artikel wurde für eine App geschrieben, die in einem Docker-Container ausgeführt wird. In einem Docker-Container hat die App immer denselben Pfad und daher denselben Anwendungsdiskriminator. Apps, die in mehreren Umgebungen ausgeführt werden (z. B. lokal und bereitgestellt), müssen den Standard-Anwendungsdiskriminator für die Umgebung festlegen. Das Ausführen einer App in mehreren Umgebungen liegt außerhalb des Umfangs dieses Artikels.

Die folgenden NuGet-Pakete sind für die in diesem Artikel verwendeten Datenschutzerweiterungen erforderlich:

Schützen von Schlüsseln mit Azure Key Vault (ProtectKeysWithAzureKeyVault)

Um lokal mit Azure Key Vault mit Entwickleranmeldeinformationen zu interagieren, melden Sie sich entweder in Visual Studio bei Ihrem Speicherkonto an, oder melden Sie sich mit der Azure CLI an. Wenn Sie die Azure CLI noch nicht installiert haben, erfahren Sie, wie Sie die Azure CLI installieren. Sie können den folgenden Befehl im PowerShell-Bereich "Entwicklertools" in Visual Studio oder über eine Befehlsshell ausführen, wenn Visual Studio nicht verwendet wird:

az login

Weitere Informationen finden Sie unter Anmelden bei Azure mithilfe von Entwicklertools.

Beim Einrichten des Schlüsseltresors im Entra- oder Azure-Portal:

  • Konfigurieren Sie den Schlüsseltresor für die Verwendung der rollenbasierten Zugriffssteuerung (Azure Role-Based Access Control, RABC). Wenn Sie nicht in einem virtuellen Azure-Netzwerk arbeiten, einschließlich für lokale Entwicklung und Tests, bestätigen Sie, dass der öffentliche Zugriff auf den Netzwerkschrittaktiviert ist (aktiviert). Das Aktivieren des öffentlichen Zugriffs macht nur den Schlüsseltresor-Endpunkt verfügbar. Authentifizierte Konten sind weiterhin für den Zugriff erforderlich.

  • Erstellen Sie eine Azure verwaltete Identity (oder fügen Sie eine Rolle zum bestehenden verwalteten Identity hinzu, die Sie zur Nutzung planen) mit der Key Vault Crypto Benutzer Rolle. Weisen Sie das verwaltete Identity dem Azure App-Dienst zu, der die Bereitstellung hostet: Einstellungen>Identity>Vom Benutzer zugewiesen>Hinzufügen.

    Note

    Wenn Sie auch beabsichtigen, eine App lokal mit einem autorisierten Benutzer für blob-Zugriff mithilfe der Azure CLI oder der Azure Service Authentication von Visual Studio auszuführen, fügen Sie Ihr Entwickler-Azure-Benutzerkonto in Access Control (IAM) mit der Rolle "Key Vault Crypto User" hinzu. Wenn Sie die Azure CLI über Visual Studio verwenden möchten, führen Sie den az login Befehl im PowerShell-Bereich "Entwicklertools" aus, und folgen Sie den Anweisungen, um sich beim Mandanten zu authentifizieren.

  • Wenn die Schlüsselverschlüsselung aktiv ist, enthalten Schlüssel in der Schlüsseldatei den Kommentar "This key is encrypted with Azure Key Vault." Nach dem Starten der App wählen Sie den Befehl "Ansicht/Bearbeiten " aus dem Kontextmenü am Ende der Schlüsselzeile aus, um zu bestätigen, dass ein Schlüssel vorhanden ist, auf den die Sicherheit des Schlüsseltresors angewendet wurde.

  • Optional können Sie die automatische Schlüsseltresor-Schlüsselrotation aktivieren, ohne sich um das Entschlüsseln von Ladungen mit Schutz von Daten-Schlüsseln basierend auf abgelaufenen/rotierten Schlüsseltresor-Schlüsseln zu sorgen. Jeder generierte Schutz von Daten-Schlüssel enthält einen Verweis auf den Schlüsseltresor-Schlüssel, der zur Verschlüsselung verwendet wurde. Stellen Sie einfach sicher, dass Sie abgelaufene Schlüssel im Schlüsseltresor beibehalten und sie nicht löschen. Verwenden Sie außerdem einen versionslosen Schlüsselbezeichner in der Schlüsseltresorkonfiguration der App, bei der keine Schlüssel-GUID am Ende des Bezeichners platziert wird (Beispiel: https://contoso.vault.azure.net/keys/data-protection). Verwenden Sie einen ähnlichen Rotationszeitraum für beide Schlüssel. Dabei sollte der Schlüsseltresorschlüssel häufiger rotiert werden als der Schlüssel für den Datenschutz, um sicherzustellen, dass zum Zeitpunkt der Rotation des Schlüssels für den Datenschutz ein neuer Schlüsseltresorschlüssel zum Einsatz kommt.

Der Schutz von Schlüsseln mit Azure Key Vault implementiert eine IXmlEncryptor Funktion, die automatische Datenschutzeinstellungen deaktiviert, einschließlich des Speicherorts des Schlüsselrings. Um den Azure Blob Storage-Anbieter zu konfigurieren, damit die Schlüssel im Blob Storage gespeichert werden, folgen Sie dem Leitfaden in „Schlüsselspeicheranbieter in ASP.NET Core“ und rufen Sie eine der PersistKeysToAzureBlobStorage Überladungen in der App auf. Das folgende Beispiel verwendet das Überladen, das eine Blob-URI und eine Token-Anmeldeinformation (TokenCredential) akzeptiert und auf eine Azure-verwaltete Identity für rollenbasierte Zugriffssteuerung (RBAC) angewiesen ist.

Um den Azure Key Vault-Anbieter zu konfigurieren, rufen Sie eine der „ProtectKeysWithAzureKeyVault“-Überladungen auf. Das folgende Beispiel verwendet das Überladen, das Schlüsselkennung und Token-Anmeldeinformation akzeptiert („TokenCredential“), wobei in der Produktion auf eine verwaltete Identity für RBAC („ManagedIdentityCredential“) oder während der Entwicklung und des Testens auf eine DefaultAzureCredential zurückgegriffen wird. Andere Überladungen akzeptieren entweder einen Schlüsseltresor-Client oder eine App-Client-ID mit geheimem Clientschlüssel. Weitere Informationen finden Sie unter Schlüsselspeicheranbieter in ASP.NET Core.

Weitere Informationen zur API und Authentifizierung des Azure SDK finden Sie unter Authentifizieren von .NET-Apps für Azure-Dienste mithilfe der Azure-Bibliothek Identity und Bereitstellen des Zugriffs auf Schlüsseltresorschlüssel, Zertifikate und geheime Schlüssel mit rollenbasierter Azure-Zugriffssteuerung. Anleitungen zur Protokollierung finden Sie unter Protokollierung mit dem Azure SDK für .NET: Protokollierung ohne Clientregistrierung. Für Apps, die Dependency Injection verwenden, kann eine App AddAzureClientsCore aufrufen und true an enableLogForwarding übergeben, um die Protokollierungsinfrastruktur zu erstellen und zu verbinden.

Informationen zum Erstellen eines Schlüssels im Azure-Portal finden Sie in der Schnellstartanleitung: Festlegen und Abrufen eines Schlüssels aus Azure Key Vault mithilfe des Azure-Portals. Geben Sie dem Schlüssel mindestens Get, Unwrap Key, und Wrap Key Berechtigungen. Notieren Sie die Schlüssel-ID zur Verwendung in der App-Konfiguration. Wenn Sie beabsichtigen, die automatische Drehung des Schlüsseltresorschlüssels zu aktivieren, notieren Sie den versionslosen Schlüsselbezeichner, wobei keine Schlüssel-GUID am Ende des Bezeichners platziert wird (Beispiel: https://contoso.vault.azure.net/keys/data-protection).

In der Program Datei, in der Dienste registriert werden:

TokenCredential? credential;

if (builder.Environment.IsProduction())
{
    credential = new ManagedIdentityCredential("{MANAGED IDENTITY CLIENT ID}");
}
else
{
    // Local development and testing only
    DefaultAzureCredentialOptions options = new()
    {
        // Specify the tenant ID to use the dev credentials when running the app locally
        // in Visual Studio.
        VisualStudioTenantId = "{TENANT ID}",
        SharedTokenCacheTenantId = "{TENANT ID}"
    };

    credential = new DefaultAzureCredential(options);
}

builder.Services.AddDataProtection()
    .SetApplicationName("{APPLICATION NAME}")
    .PersistKeysToAzureBlobStorage(new Uri("{BLOB URI}"), credential)
    .ProtectKeysWithAzureKeyVault(new Uri("{KEY IDENTIFIER}"), credential);

{MANAGED IDENTITY CLIENT ID}: Die Azure verwaltete Identity Client-ID (GUID).

{TENANT ID}: Mandanten-ID.

{APPLICATION NAME}: SetApplicationName legt den eindeutigen Namen dieser App im Datenschutzsystem fest. Der Wert sollte für alle Bereitstellungen der App übereinstimmen.

{BLOB URI}: Vollständiger URI für die Schlüsseldatei. Der URI wird von Azure Storage generiert, wenn Sie die Schlüsseldatei erstellen. NICHT SAS nutzen.

{KEY IDENTIFIER}: Azure Key Vault-Schlüsselbezeichner, der für die Schlüsselverschlüsselung verwendet wird. Eine Zugriffsrichtlinie ermöglicht der Anwendung den Zugriff auf den Schlüsseltresor mit Get, Unwrap Keyund Wrap Key Berechtigungen. Die Version des Schlüssels wird aus dem Schlüssel im Entra- oder Azure-Portal abgerufen, nachdem er erstellt wurde. Wenn Sie die automatische Drehung des Schlüsseltresorschlüssels aktivieren, stellen Sie sicher, dass Sie in der Schlüsseltresorkonfiguration der App einen versionslosen Schlüsselbezeichner verwenden, bei dem keine Schlüssel-GUID am Ende des Bezeichners platziert wird (Beispiel: https://contoso.vault.azure.net/keys/data-protection).

Damit eine App mit Azure Key Vault kommunizieren und autorisieren kann, muss das Azure.Identity NuGet-Paket von der App referenziert werden.

Note

Eine Anleitung zum Hinzufügen von Paketen zu .NET-Anwendungen finden Sie in den Artikeln unter Pakete installieren und verwalten unter Workflow für die Paketnutzung (NuGet-Dokumentation). Überprüfen Sie unter NuGet.org, ob die richtige Paketversion verwendet wird.

Note

In Nicht-Produktionsumgebungen wird im vorherigen Beispiel die Authentifizierung mithilfe von DefaultAzureCredential vereinfacht. Dabei werden Anmeldeinformationen kombiniert, die sowohl in Azure-Hostingumgebungen als auch in der lokalen Entwicklung verwendet werden, während Apps entwickelt werden, die in Azure bereitgestellt werden. Weitere Informationen finden Sie unter Authentifizieren von von Azure gehosteten .NET-Apps für Azure-Ressourcen mithilfe einer vom System zugewiesenen verwalteten Identität.

Wenn die App die älteren Azure-Pakete (Microsoft.AspNetCore.DataProtection.AzureStorage und Microsoft.AspNetCore.DataProtection.AzureKeyVault) verwendet, empfehlen wir, diese Verweise zu entfernen und auf die Azure.Extensions.AspNetCore.DataProtection.Blobs Pakete Azure.Extensions.AspNetCore.DataProtection.Keys zu aktualisieren. Die neueren Pakete behandeln wichtige Sicherheits- und Stabilitätsprobleme.

Alternative SAS-Ansatz für Shared-Access-Signaturen: Als Alternative zur Verwendung eines verwalteten Identity, um auf den Schlüssel-Blob in Azure Blob Storage zuzugreifen, können Sie die PersistKeysToAzureBlobStorage-Überladung aufrufen, die eine Blob-URI mit einem SAS-Token akzeptiert. Das folgende Beispiel verwendet weiterhin entweder ein ManagedIdentityCredential (Produktion) oder ein DefaultAzureCredential (Entwicklung und Test) für sein TokenCredential, wie im vorhergehenden Beispiel zu sehen ist:

builder.Services.AddDataProtection()
    .SetApplicationName("{APPLICATION NAME}")
    .PersistKeysToAzureBlobStorage(new Uri("{BLOB URI WITH SAS}"))
    .ProtectKeysWithAzureKeyVault(new Uri("{KEY IDENTIFIER}"), credential);

{APPLICATION NAME}: SetApplicationName legt den eindeutigen Namen dieser App im Datenschutzsystem fest. Der Wert sollte für alle Bereitstellungen der App übereinstimmen.

{BLOB URI WITH SAS}: Der vollständige URI, in dem die Schlüsseldatei mit dem SAS-Token als Abfragezeichenfolgenparameter gespeichert werden soll. Der URI wird von Azure Storage generiert, wenn Sie eine SAS für die hochgeladene Schlüsseldatei anfordern.

{KEY IDENTIFIER}: Azure Key Vault-Schlüsselbezeichner, der für die Schlüsselverschlüsselung verwendet wird. Eine Zugriffsrichtlinie ermöglicht der Anwendung den Zugriff auf den Schlüsseltresor mit Get, Unwrap Keyund Wrap Key Berechtigungen. Die Version des Schlüssels wird aus dem Schlüssel im Entra- oder Azure-Portal abgerufen, nachdem er erstellt wurde. Wenn Sie die automatische Drehung des Schlüsseltresorschlüssels aktivieren, stellen Sie sicher, dass Sie in der Schlüsseltresorkonfiguration der App einen versionslosen Schlüsselbezeichner verwenden, bei dem keine Schlüssel-GUID am Ende des Bezeichners platziert wird (Beispiel: https://contoso.vault.azure.net/keys/data-protection).

Schlüssel im Dateisystem speichern („PersistKeysToFileSystem“)

Um Schlüssel auf einer UNC-Freigabe statt am Standardspeicherort %LOCALAPPDATA% zu speichern, konfigurieren Sie das System mit PersistKeysToFileSystem:

builder.Services.AddDataProtection()
    .PersistKeysToFileSystem(new DirectoryInfo(@"\\server\share\directory\"));

Warning

Wenn Sie den Schlüsselpersistenzspeicherort ändern, verschlüsselt das System ruhende Schlüssel nicht mehr automatisch, da es nicht weiß, ob DPAPI ein geeigneter Verschlüsselungsmechanismus ist.

Beibehalten von Schlüsseln in einer Datenbank (PersistKeysToDbContext)

Um Schlüssel in einer Datenbank mit EntityFramework zu speichern, konfigurieren Sie das System mit dem Paket Microsoft.AspNetCore.DataProtection.EntityFrameworkCore:

builder.Services.AddDataProtection()
    .PersistKeysToDbContext<SampleDbContext>();

Der vorangehende Code speichert die Schlüssel in der konfigurierten Datenbank. Der verwendete Datenbankkontext muss IDataProtectionKeyContext implementieren. IDataProtectionKeyContext macht die DataProtectionKeys-Eigenschaft verfügbar.

public DbSet<DataProtectionKey> DataProtectionKeys { get; set; } = null!;

Diese Eigenschaft stellt die Tabelle dar, in der die Schlüssel gespeichert werden. Erstellen Sie die Tabelle manuell oder mithilfe von DbContext-Migrationen. Weitere Informationen finden Sie unter DataProtectionKey.

Schützen der Schlüsselkonfiguration-API („ProtectKeysWith\*“)

Sie können das System so konfigurieren, dass ruhende Schlüssel geschützt werden, indem Sie eine der ProtectKeysWith\* Konfigurations-APIs aufrufen. Betrachten Sie das folgende Beispiel, das Schlüssel auf einer UNC-Freigabe speichert und diese Schlüssel im Ruhezustand mit einem bestimmten X.509-Zertifikat verschlüsselt.

Sie können ein X509Certificate2 zu einem ProtectKeysWithCertificate aus einer Datei bereitstellen, indem Sie X509CertificateLoader.LoadCertificateFromFile aufrufen:

builder.Services.AddDataProtection()
    .PersistKeysToFileSystem(new DirectoryInfo(@"\\server\share\directory\"))
    .ProtectKeysWithCertificate(
        new X509Certificate2("certificate.pfx", builder.Configuration["CertificatePassword"]));

Im folgenden Codebeispiel wird das Laden eines Zertifikats mithilfe eines Fingerabdrucks veranschaulicht:

builder.Services.AddDataProtection()
    .PersistKeysToFileSystem(new DirectoryInfo(@"\\server\share\directory\"))
    .ProtectKeysWithCertificate(builder.Configuration["CertificateThumbprint"]);

Sie können für X509Certificate2 ein ProtectKeysWithCertificate angeben, z. B. ein Zertifikat, das aus einer Datei geladen wurde:

builder.Services.AddDataProtection()
    .PersistKeysToFileSystem(new DirectoryInfo(@"\\server\share\directory\"))
    .ProtectKeysWithCertificate(
        new X509Certificate2("certificate.pfx", builder.Configuration["CertificatePassword"]));

Im folgenden Codebeispiel wird das Laden eines Zertifikats mithilfe eines Fingerabdrucks veranschaulicht:

builder.Services.AddDataProtection()
    .PersistKeysToFileSystem(new DirectoryInfo(@"\\server\share\directory\"))
    .ProtectKeysWithCertificate(builder.Configuration["CertificateThumbprint"]);

Beispiele und Erläuterungen zu den integrierten Schlüsselverschlüsselungsmechanismen finden Sie unter "Ruheschlüsselverschlüsselung" in Windows und Azure mit ASP.NET Core.

Aufheben des Schutzes von Schlüsseln mit einem beliebigen Zertifikat (UnprotectKeysWithAnyCertificate)

Sie können Zertifikate rotieren und ruhende Schlüssel entschlüsseln, indem Sie ein Array von X509Certificate2-Zertifikaten mit UnprotectKeysWithAnyCertificate verwenden:

builder.Services.AddDataProtection()
    .PersistKeysToFileSystem(new DirectoryInfo(@"\\server\share\directory\"))
    .ProtectKeysWithCertificate(
        new X509Certificate2("certificate.pfx", builder.Configuration["CertificatePassword"]))
    .UnprotectKeysWithAnyCertificate(
        new X509Certificate2("certificate_1.pfx", builder.Configuration["CertificatePassword_1"]),
        new X509Certificate2("certificate_2.pfx", builder.Configuration["CertificatePassword_2"]));

Festlegen der Standardschlüssellebensdauer (SetDefaultKeyLifetime)

Verwenden Sie SetDefaultKeyLifetime, um das System für die Verwendung einer Schlüssellebensdauer von 14 Tagen anstelle der Standarddauer von 90 Tagen zu konfigurieren:

builder.Services.AddDataProtection()
    .SetDefaultKeyLifetime(TimeSpan.FromDays(14));

Festlegen des Anwendungsnamens (SetApplicationName)

Standardmäßig isoliert das Datenschutzsystem Apps basierend auf ihren Inhaltsstammpfaden voneinander, auch wenn sie dasselbe physische Schlüsselrepository verwenden. Diese Isolation verhindert, dass die Apps die geschützten Nutzdaten anderer Apps verstehen.

So nutzen Sie geschützte Nutzdaten gemeinsam für Apps

  • Konfigurieren Sie SetApplicationName in jeder App mit demselben Wert.
  • Verwenden Sie für alle Apps dieselbe Version des Datenschutz-API-Stapels. Führen Sie eine der folgenden Aktionen in den Projektdateien der Apps aus:
builder.Services.AddDataProtection()
    .SetApplicationName("<sharedApplicationName>");

SetApplicationName legt den DataProtectionOptions.ApplicationDiscriminator intern fest. Zu Problembehandlungszwecken kann der Wert, der dem Diskriminator vom Framework zugewiesen wurde, mit dem folgenden Code protokolliert werden, der nach dem Aufbau von WebApplication in Program.cs platziert wird.

var discriminator = app.Services.GetRequiredService<IOptions<DataProtectionOptions>>()
    .Value.ApplicationDiscriminator;
app.Logger.LogInformation("ApplicationDiscriminator: {ApplicationDiscriminator}", discriminator);

Weitere Informationen zur Verwendung des Diskriminators finden Sie in den folgenden Abschnitten weiter unten in diesem Artikel:

Warning

In .NET 6 normalisiert WebApplicationBuilder den Inhaltsstammpfad so, dass er mit DirectorySeparatorChar endet. Unter Windows endet der Inhaltsstammpfad beispielsweise auf \ und unter Linux auf /. Andere Hosts normalisieren den Pfad nicht. Die meisten Apps, die von HostBuilder oder WebHostBuilder migriert werden, haben nicht denselben App-Namen, da sie nicht auf DirectorySeparatorChar enden. Um dieses Problem zu umgehen, entfernen Sie das Verzeichnistrennzeichen und legen den App-Namen manuell fest, wie im folgenden Code gezeigt:

using System.Reflection;
using Microsoft.AspNetCore.DataProtection;

var builder = WebApplication.CreateBuilder(args);

var trimmedContentRootPath = 
    builder.Environment.ContentRootPath.TrimEnd(Path.DirectorySeparatorChar);

builder.Services.AddDataProtection().SetApplicationName(trimmedContentRootPath);

var app = builder.Build();

app.MapGet("/", () => Assembly.GetEntryAssembly()!.GetName().Name);

app.Run();

Automatische Schlüsselgenerierung deaktivieren (DisableAutomaticKeyGeneration)

Möglicherweise möchten Sie in Ihrem Szenario nicht, dass eine App Schlüssel automatisch rotiert (neue Schlüssel erstellt), wenn diese demnächst ablaufen. Ein Beispiel für dieses Szenario sind Apps, die in einer hierarchischen Beziehung (primär/sekundär) eingerichtet wurden, bei der nur die primäre App für Schlüsselverwaltungsaspekte verantwortlich ist und sekundäre Apps lediglich über eine schreibgeschützte Ansicht des Schlüsselrings verfügen. Die sekundären Apps können so konfiguriert werden, dass der Schlüsselring als schreibgeschützt behandelt wird, indem das System mit DisableAutomaticKeyGeneration konfiguriert wird:

builder.Services.AddDataProtection()
    .DisableAutomaticKeyGeneration();

Isolation pro Anwendung

Wenn das Datenschutzsystem von einem ASP.NET Core-Host bereitgestellt wird, isoliert es Apps automatisch voneinander, auch wenn diese Apps unter demselben Workerprozesskonto ausgeführt werden und dasselbe Hauptschlüsselmaterial verwenden. Dies ähnelt dem IsolateApps-Modifizierer aus dem <machineKey>-Element von „System.Web“.

Der Isolationsmechanismus betrachtet jede App auf dem lokalen Computer als eindeutigen Mandanten, sodass der IDataProtector als Stamm für jede App automatisch die App-ID als Diskriminator enthält (ApplicationDiscriminator). Die eindeutige ID der App ist ihr physischer Pfad:

  • Bei in IIS gehosteten Apps ist die eindeutige ID der physische IIS-Pfad der App. Wenn eine App in einer Webfarmumgebung bereitgestellt wird, ist dieser Wert unveränderlich, sofern die IIS-Umgebungen auf allen Computern in der Webfarm gleich konfiguriert sind.
  • Bei selbstgehosteten Apps, die auf dem Kestrel-Server ausgeführt werden, ist die eindeutige ID der physische Pfad zur App auf dem Datenträger.

Der eindeutige Bezeichner ist so konzipiert, dass er beim Zurücksetzen beibehalten wird – sowohl für die einzelne App als auch für den Computer selbst.

Bei diesem Isolationsmechanismus wird davon ausgegangen, dass die Apps nicht böswillig sind. Eine böswillige App kann sich immer auf jede andere App auswirken, die unter demselben Workerprozesskonto ausgeführt wird. In einer gemeinsam genutzten Hostingumgebung, in der Apps gegenseitig nicht vertrauenswürdig sind, sollte der Hostinganbieter Maßnahmen ergreifen, um die Isolation zwischen Apps auf Betriebssystemebene sicherzustellen. Dies schließt auch die Trennung der zugrunde liegenden Schlüsselrepositorys der Apps ein.

Wenn das Datenschutzsystem nicht von einem ASP.NET Core-Host bereitgestellt wird (z. B. wenn Sie ihn über den konkreten Typ DataProtectionProvider instanziieren), ist die App-Isolation standardmäßig deaktiviert. Wenn die App-Isolation deaktiviert ist, können alle Apps, die dasselbe Schlüsselmaterial verwenden, Nutzdaten gemeinsam nutzen, solange sie die entsprechenden Zwecke bereitstellen. Um in einer solchen Umgebung App-Isolation bereitzustellen, rufen Sie die SetApplicationName-Methode für das Konfigurationsobjekt auf und geben einen eindeutigen Namen für jede App an.

Datenschutz und App-Isolation

Berücksichtigen Sie die folgenden Punkte bei der App-Isolation:

  • Wenn mehrere Apps auf dasselbe Schlüsselrepository verweisen, wird beabsichtigt, dass die Apps dasselbe Hauptschlüsselmaterial gemeinsam nutzen. Datenschutz wird unter der Annahme entwickelt, dass alle Apps, die einen Schlüsselring teilen, auf alle Elemente in diesem Schlüsselring zugreifen können. Der eindeutige Bezeichner der Anwendung wird verwendet, um anwendungsspezifische Schlüssel zu isolieren, die von den bereitgestellten Schlüsseln des Schlüsselrings abgeleitet werden. Es wird nicht erwartet, dass Berechtigungen auf Elementebene, wie sie z. B. von Azure KeyVault bereitgestellt werden, verwendet werden, um eine zusätzliche Isolation zu erzwingen. Beim Versuch, Berechtigungen auf Elementebene zu verwenden, werden Anwendungsfehler generiert. Wenn Sie sich nicht auf die integrierte Anwendungsisolation verlassen möchten, sollten Sie separate Schlüsselspeicherorte verwenden, die nicht von Anwendungen gemeinsam genutzt werden.

  • Der Anwendungsdiskriminator (ApplicationDiscriminator) wird verwendet, um verschiedenen Apps zu ermöglichen, dasselbe Hauptschlüsselmaterial gemeinsam zu nutzen, ihre kryptografischen Nutzdaten jedoch voneinander getrennt zu halten. Damit die Apps die kryptografischen Nutzdaten der jeweils anderen lesen können, müssen sie über denselben Anwendungsdiskriminator verfügen, der durch Aufrufen von SetApplicationName festgelegt werden kann.

  • Wenn eine App kompromittiert wurde (z. B. durch einen RCE-Angriff), muss das gesamte Hauptschlüsselmaterial, auf das diese App zugreifen kann, ebenfalls als kompromittiert angesehen werden, unabhängig vom Schutzstatus im Ruhezustand. Dies bedeutet auch, dass, wenn zwei Apps auf dasselbe Repository zeigen, eine Kompromittierung von einer funktional einer Kompromittierung von beiden entspricht, selbst wenn sie unterschiedliche App-Diskriminatoren verwenden.

    Diese Klausel, die "in funktionaler Hinsicht einem Kompromiss beider gleichwertig ist", gilt auch dann, wenn die beiden Apps unterschiedliche Mechanismen zum Schutz der Schlüssel im Ruhezustand verwenden. Dies ist in der Regel keine zu erwartende Konfiguration. Der Mechanismus für den Schutz ruhender Daten soll Schutz bieten, wenn ein Cyberangreifer Lesezugriff auf das Repository erhält. Cyber-Angreifende, die Schreibzugriff auf das Repository erlangen (z. B. indem sie die Codeausführungsberechtigung innerhalb einer App erhalten haben), können bösartige Schlüssel in den Speicher einfügen. Das Datenschutzsystem bietet absichtlich keinen Schutz vor Cyber-Angreifer*innen, die Schreibzugriff auf das Schlüsselrepository erlangen.

  • Wenn Apps wirklich isoliert voneinander bleiben müssen, sollten sie unterschiedliche Schlüsselrepositorys verwenden. Dies liegt natürlich außerhalb der Definition von „isoliert“. Apps sind nicht isoliert, wenn sie alle über Lese- und Schreibzugriff auf die Datenspeicher der anderen verfügen.

Ändern von Algorithmen mit UseCryptographicAlgorithms

Mit dem Datenschutzstapel können Sie den Standardalgorithmus ändern, der von neu generierten Schlüsseln verwendet wird. Die einfachste Möglichkeit besteht darin, im Konfigurationsrückruf UseCryptographicAlgorithms aufzurufen:

builder.Services.AddDataProtection()
    .UseCryptographicAlgorithms(new AuthenticatedEncryptorConfiguration
    {
        EncryptionAlgorithm = EncryptionAlgorithm.AES_256_CBC,
        ValidationAlgorithm = ValidationAlgorithm.HMACSHA256
    });

Der Standardverschlüsselungsalgorithmus ist AES-256-CBC, und der Standardüberprüfungsalgorithmus ist HMACSHA256. Die Standardrichtlinie kann von Systemadministrator*innen über eine computerweite Richtlinie festgelegt werden, aber ein expliziter Aufruf von UseCryptographicAlgorithms setzt die Standardrichtlinie außer Kraft.

Durch Aufrufen von UseCryptographicAlgorithms können Sie den gewünschten Algorithmus aus einer vordefinierten Liste integrierter Algorithmen angeben. Um die Implementierungsdetails des Algorithmus müssen Sie sich nicht kümmern. Im obigen Szenario versucht das Datenschutzsystem, bei einer Ausführung unter Windows die CNG-Implementierung von AES zu verwenden. Andernfalls greift es auf die verwaltete System.Security.Cryptography.Aes-Klasse zurück.

Sie können eine Implementierung manuell über einen Aufruf von UseCustomCryptographicAlgorithms angeben.

Tip

Das Ändern von Algorithmen wirkt sich nicht auf vorhandene Schlüssel im Schlüsselring aus. Dies wirkt sich nur auf neu generierte Schlüssel aus.

Festlegen benutzerdefinierter verwalteter Algorithmen

Um benutzerdefinierte verwaltete Algorithmen anzugeben, erstellen Sie eine Instanz von ManagedAuthenticatedEncryptorConfiguration, die auf die Implementierungstypen verweist:

builder.Services.AddDataProtection()
    .UseCustomCryptographicAlgorithms(new ManagedAuthenticatedEncryptorConfiguration
    {
        // A type that subclasses SymmetricAlgorithm
        EncryptionAlgorithmType = typeof(Aes),

        // Specified in bits
        EncryptionAlgorithmKeySize = 256,

        // A type that subclasses KeyedHashAlgorithm
        ValidationAlgorithmType = typeof(HMACSHA256)
    });

Im Allgemeinen müssen die *Type-Eigenschaften auf konkrete, instanziierbare (über einen öffentlichen parameterlosen ctor) Implementierungen von SymmetricAlgorithm und KeyedHashAlgorithm verweisen, wobei die Sonderfälle im System einige Werte wie z. B typeof(Aes) zur Vereinfachung aufweisen.

Note

Ein SymmetricAlgorithm muss eine Schlüssellänge von ≥ 128 Bit und eine Blockgröße von ≥ 64 Bit aufweisen und die Verschlüsselung im CBC-Modus mit PKCS #7-Auffüllung unterstützen. Der KeyedHashAlgorithm muss eine Hashgröße von >= 128 Bit aufweisen und Schlüssel mit einer Länge unterstützen, die der Hashlänge des Hashalgorithmus entspricht. KeyedHashAlgorithm muss nicht unbedingt HMAC sein.

Angeben benutzerdefinierter Windows-CNG-Algorithmen

Um einen benutzerdefinierten Windows-CNG-Algorithmus mithilfe der Verschlüsselung im CBC-Modus mit HMAC-Validierung anzugeben, erstellen Sie eine Instanz von CngCbcAuthenticatedEncryptorConfiguration, die die Algorithmusinformationen enthält:

builder.Services.AddDataProtection()
    .UseCustomCryptographicAlgorithms(new CngCbcAuthenticatedEncryptorConfiguration
    {
        // Passed to BCryptOpenAlgorithmProvider
        EncryptionAlgorithm = "AES",
        EncryptionAlgorithmProvider = null,

        // Specified in bits
        EncryptionAlgorithmKeySize = 256,

        // Passed to BCryptOpenAlgorithmProvider
        HashAlgorithm = "SHA256",
        HashAlgorithmProvider = null
    });

Note

Der symmetrische Blockchiffre-Algorithmus muss eine Schlüssellänge von >= 128 Bit und eine Blockgröße von >= 64 Bit aufweisen und die Verschlüsselung im CBC-Modus mit PKCS #7-Auffüllung unterstützen. Der Hashalgorithmus muss eine Digestgröße von >= 128 Bit aufweisen und das Öffnen mit dem Flag BCRYPT_ALG_HANDLE_HMAC_FLAG unterstützen. Die *Provider-Eigenschaften können auf NULL festgelegt werden, um den Standardanbieter für den angegebenen Algorithmus zu verwenden. Weitere Informationen finden Sie in der Dokumentation zu BCryptOpenAlgorithmProvider.

Um einen benutzerdefinierten Windows-CNG-Algorithmus mithilfe der Verschlüsselung im Galois/Counter-Modus mit Validierung anzugeben, erstellen Sie eine Instanz von CngGcmAuthenticatedEncryptorConfiguration, die die Algorithmusinformationen enthält:

builder.Services.AddDataProtection()
    .UseCustomCryptographicAlgorithms(new CngGcmAuthenticatedEncryptorConfiguration
    {
        // Passed to BCryptOpenAlgorithmProvider
        EncryptionAlgorithm = "AES",
        EncryptionAlgorithmProvider = null,

        // Specified in bits
        EncryptionAlgorithmKeySize = 256
    });

Note

Der symmetrische Blockchiffre-Algorithmus muss eine Schlüssellänge von >= 128 Bit und eine Blockgröße von genau 128 Bit aufweisen und die GCM-Verschlüsselung unterstützen. Sie können die EncryptionAlgorithmProvider-Eigenschaft auf NULL festlegen, um den Standardanbieter für den angegebenen Algorithmus zu verwenden. Weitere Informationen finden Sie in der Dokumentation zu BCryptOpenAlgorithmProvider.

Angeben anderer benutzerdefinierter Algorithmen

Obwohl das Datenschutzsystem nicht als besondere API verfügbar gemacht wird, ist es erweiterbar genug, um die Angabe fast jeden Algorithmustyps zu ermöglichen. Es ist beispielsweise möglich, alle Schlüssel, die in einem Hardwaresicherheitsmodul (HSM) enthalten sind, beizubehalten und eine benutzerdefinierte Implementierung der wichtigsten Ver- und Entschlüsselungsroutinen bereitzustellen. Weitere Informationen finden Sie unter IAuthenticatedEncryptor in Kryptografieerweiterbarkeit in Core.

Beibehalten von Schlüsseln beim Hosten in einem Docker-Container

Beim Hosten in einem Docker-Container sollten Schlüssel mit einer der folgenden Optionen verwaltet werden:

  • Ein Ordner, der ein Docker-Volume ist und über die Lebensdauer des Containers hinaus beibehalten wird, wie ein freigegebenes Volume oder ein vom Host bereitgestelltes Volume.
  • Bei einem externen Anbieter, z. B. Azure Blob Storage (siehe Abschnitt ProtectKeysWithAzureKeyVault) oder Redis

Beibehalten von Schlüsseln mit Redis

Zum Speichern von Schlüsseln sollten nur Redis-Versionen verwendet werden, die Redis Data Persistence unterstützen. Azure Blob Storage ist persistent und kann zum Speichern von Schlüsseln verwendet werden. Weitere Informationen finden Sie in diesem GitHub-Issue.

Logging

Aktivieren Sie die Information oder niedrigere Protokollierungsebene, um Probleme zu diagnostizieren. Die folgende appsettings.json Datei ermöglicht die Informationsprotokollierung der Datenschutz-API:

{
  "Logging": {
    "LogLevel": {
      "Default": "Information",
      "Microsoft.AspNetCore": "Warning",
      "Microsoft.AspNetCore.DataProtection": "Information"
    }
  },
  "AllowedHosts": "*"
}

Weitere Informationen zur Protokollierung finden Sie unter Protokollierung in .NET und ASP.NET Core.

Weitere Ressourcen

Wenn das Datenschutzsystem initialisiert wird, werden Standardeinstellungen basierend auf der Betriebsumgebung angewandt. Diese Einstellungen eignen sich für Apps, die auf einem einzelnen Computer ausgeführt werden. Es gibt jedoch Fälle, in denen Entwickler*innen die Standardeinstellungen ändern möchten:

  • Die App ist auf mehrere Computer verteilt.
  • Aus Compliance-Gründen.

Für diese Szenarien bietet das Datenschutzsystem eine umfangreiche Konfigurations-API.

Warning

Ähnlich wie bei Konfigurationsdateien sollte der Schlüsselring für den Datenschutz mit entsprechenden Berechtigungen geschützt werden. Sie können ruhende Schlüssel verschlüsseln, wodurch jedoch nicht verhindert wird, dass Cyberangriffe neue Schlüssel erstellen. Folglich wird die Sicherheit Ihrer App beeinträchtigt. Der mit Datenschutz konfigurierte Speicherort sollte auf die App selbst beschränkt sein, ähnlich wie beim Schutz von Konfigurationsdateien. Wenn Sie sich beispielsweise dafür entscheiden, Ihren Schlüsselring auf dem Datenträger zu speichern, verwenden Sie Dateisystemberechtigungen. Stellen Sie sicher, dass nur die Identität, unter der Ihre Web-App ausgeführt wird, Lese-, Schreib- und Zugriff auf dieses Verzeichnis hat. Wenn Sie Azure Blob Storage verwenden, sollte nur die Web-App die Möglichkeit haben, neue Einträge im BLOB-Speicher zu lesen, zu schreiben oder zu erstellen.

Die Erweiterungsmethode AddDataProtection gibt eine IDataProtectionBuilderErweiterungsmethode zurück, die Erweiterungsmethoden verfügbar macht, die Sie verketten können, um Datenschutzoptionen zu konfigurieren.

Die folgenden NuGet-Pakete sind für die in diesem Artikel verwendeten Datenschutzerweiterungen erforderlich:

Note

Eine Anleitung zum Hinzufügen von Paketen zu .NET-Anwendungen finden Sie in den Artikeln unter Pakete installieren und verwalten unter Workflow für die Paketnutzung (NuGet-Dokumentation). Überprüfen Sie unter NuGet.org, ob die richtige Paketversion verwendet wird.

Schützen von Schlüsseln mit Azure Key Vault (ProtectKeysWithAzureKeyVault)

Um lokal mit Azure Key Vault mit Entwickleranmeldeinformationen zu interagieren, melden Sie sich entweder in Visual Studio bei Ihrem Speicherkonto an, oder melden Sie sich mit der Azure CLI an. Wenn Sie die Azure CLI noch nicht installiert haben, erfahren Sie, wie Sie die Azure CLI installieren. Sie können den folgenden Befehl im PowerShell-Bereich "Entwicklertools" in Visual Studio oder über eine Befehlsshell ausführen, wenn Visual Studio nicht verwendet wird:

az login

Weitere Informationen finden Sie unter Anmelden bei Azure mithilfe von Entwicklertools.

Beim Einrichten des Schlüsseltresors im Entra- oder Azure-Portal:

  • Konfigurieren Sie den Schlüsseltresor für die Verwendung der rollenbasierten Zugriffssteuerung (Azure Role-Based Access Control, RABC). Wenn Sie nicht in einem virtuellen Azure-Netzwerk arbeiten, einschließlich für lokale Entwicklung und Tests, bestätigen Sie, dass der öffentliche Zugriff auf den Netzwerkschrittaktiviert ist (aktiviert). Das Aktivieren des öffentlichen Zugriffs macht nur den Schlüsseltresor-Endpunkt verfügbar. Authentifizierte Konten sind weiterhin für den Zugriff erforderlich.

  • Erstellen Sie eine Azure verwaltete Identity (oder fügen Sie eine Rolle zum bestehenden verwalteten Identity hinzu, die Sie zur Nutzung planen) mit der Key Vault Crypto Benutzer Rolle. Weisen Sie das verwaltete Identity dem Azure App-Dienst zu, der die Bereitstellung hostet: Einstellungen>Identity>Vom Benutzer zugewiesen>Hinzufügen.

    Note

    Wenn Sie auch beabsichtigen, eine App lokal mit einem autorisierten Benutzer für blob-Zugriff mithilfe der Azure CLI oder der Azure Service Authentication von Visual Studio auszuführen, fügen Sie Ihr Entwickler-Azure-Benutzerkonto in Access Control (IAM) mit der Rolle "Key Vault Crypto User" hinzu. Wenn Sie die Azure CLI über Visual Studio verwenden möchten, führen Sie den az login Befehl im PowerShell-Bereich "Entwicklertools" aus, und folgen Sie den Anweisungen, um sich beim Mandanten zu authentifizieren.

  • Wenn die Schlüsselverschlüsselung aktiv ist, enthalten Schlüssel in der Schlüsseldatei den Kommentar "This key is encrypted with Azure Key Vault." Nach dem Starten der App wählen Sie den Befehl "Ansicht/Bearbeiten " aus dem Kontextmenü am Ende der Schlüsselzeile aus, um zu bestätigen, dass ein Schlüssel vorhanden ist, auf den die Sicherheit des Schlüsseltresors angewendet wurde.

  • Optional können Sie die automatische Schlüsseltresor-Schlüsselrotation aktivieren, ohne sich um das Entschlüsseln von Ladungen mit Schutz von Daten-Schlüsseln basierend auf abgelaufenen/rotierten Schlüsseltresor-Schlüsseln zu sorgen. Jeder generierte Schutz von Daten-Schlüssel enthält einen Verweis auf den Schlüsseltresor-Schlüssel, der zur Verschlüsselung verwendet wurde. Stellen Sie einfach sicher, dass Sie abgelaufene Schlüssel im Schlüsseltresor beibehalten und sie nicht löschen. Verwenden Sie außerdem einen versionslosen Schlüsselbezeichner in der Schlüsseltresorkonfiguration der App, bei der keine Schlüssel-GUID am Ende des Bezeichners platziert wird (Beispiel: https://contoso.vault.azure.net/keys/data-protection). Verwenden Sie einen ähnlichen Rotationszeitraum für beide Schlüssel. Dabei sollte der Schlüsseltresorschlüssel häufiger rotiert werden als der Schlüssel für den Datenschutz, um sicherzustellen, dass zum Zeitpunkt der Rotation des Schlüssels für den Datenschutz ein neuer Schlüsseltresorschlüssel zum Einsatz kommt.

Der Schutz von Schlüsseln mit Azure Key Vault implementiert eine IXmlEncryptor Funktion, die automatische Datenschutzeinstellungen deaktiviert, einschließlich des Speicherorts des Schlüsselrings. Um den Azure Blob Storage-Anbieter zu konfigurieren, damit die Schlüssel im Blob Storage gespeichert werden, folgen Sie dem Leitfaden in „Schlüsselspeicheranbieter in ASP.NET Core“ und rufen Sie eine der PersistKeysToAzureBlobStorage Überladungen in der App auf. Das folgende Beispiel verwendet das Überladen, das eine Blob-URI und eine Token-Anmeldeinformation (TokenCredential) akzeptiert und auf eine Azure-verwaltete Identity für rollenbasierte Zugriffssteuerung (RBAC) angewiesen ist.

Um den Azure Key Vault-Anbieter zu konfigurieren, rufen Sie eine der „ProtectKeysWithAzureKeyVault“-Überladungen auf. Das folgende Beispiel verwendet das Überladen, das Schlüsselkennung und Token-Anmeldeinformation akzeptiert („TokenCredential“), wobei in der Produktion auf eine verwaltete Identity für RBAC („ManagedIdentityCredential“) oder während der Entwicklung und des Testens auf eine DefaultAzureCredential zurückgegriffen wird. Andere Überladungen akzeptieren entweder einen Schlüsseltresor-Client oder eine App-Client-ID mit geheimem Clientschlüssel. Weitere Informationen finden Sie unter Schlüsselspeicheranbieter in ASP.NET Core.

Weitere Informationen zur API und Authentifizierung des Azure SDK finden Sie unter Authentifizieren von .NET-Apps für Azure-Dienste mithilfe der Azure-Bibliothek Identity und Bereitstellen des Zugriffs auf Schlüsseltresorschlüssel, Zertifikate und geheime Schlüssel mit rollenbasierter Azure-Zugriffssteuerung. Anleitungen zur Protokollierung finden Sie unter Protokollierung mit dem Azure SDK für .NET: Protokollierung ohne Clientregistrierung. Für Apps, die Dependency Injection verwenden, kann eine App AddAzureClientsCore aufrufen und true an enableLogForwarding übergeben, um die Protokollierungsinfrastruktur zu erstellen und zu verbinden.

Informationen zum Erstellen eines Schlüssels im Azure-Portal finden Sie in der Schnellstartanleitung: Festlegen und Abrufen eines Schlüssels aus Azure Key Vault mithilfe des Azure-Portals. Geben Sie dem Schlüssel mindestens Get, Unwrap Key, und Wrap Key Berechtigungen. Notieren Sie die Schlüssel-ID zur Verwendung in der App-Konfiguration. Wenn Sie beabsichtigen, die automatische Drehung des Schlüsseltresorschlüssels zu aktivieren, notieren Sie den versionslosen Schlüsselbezeichner, wobei keine Schlüssel-GUID am Ende des Bezeichners platziert wird (Beispiel: https://contoso.vault.azure.net/keys/data-protection).

In der Program Datei, in der Dienste registriert werden:

TokenCredential? credential;

if (builder.Environment.IsProduction())
{
    credential = new ManagedIdentityCredential("{MANAGED IDENTITY CLIENT ID}");
}
else
{
    // Local development and testing only
    DefaultAzureCredentialOptions options = new()
    {
        // Specify the tenant ID to use the dev credentials when running the app locally
        // in Visual Studio.
        VisualStudioTenantId = "{TENANT ID}",
        SharedTokenCacheTenantId = "{TENANT ID}"
    };

    credential = new DefaultAzureCredential(options);
}

services.AddDataProtection()
    .SetApplicationName("{APPLICATION NAME}")
    .PersistKeysToAzureBlobStorage(new Uri("{BLOB URI}"), credential)
    .ProtectKeysWithAzureKeyVault(new Uri("{KEY IDENTIFIER}"), credential);

{MANAGED IDENTITY CLIENT ID}: Die Azure verwaltete Identity Client-ID (GUID).

{TENANT ID}: Mandanten-ID.

{APPLICATION NAME}: SetApplicationName legt den eindeutigen Namen dieser App im Datenschutzsystem fest. Der Wert sollte für alle Bereitstellungen der App übereinstimmen.

{BLOB URI}: Vollständiger URI für die Schlüsseldatei. Der URI wird von Azure Storage generiert, wenn Sie die Schlüsseldatei erstellen. NICHT SAS nutzen.

{KEY IDENTIFIER}: Azure Key Vault-Schlüsselbezeichner, der für die Schlüsselverschlüsselung verwendet wird. Eine Zugriffsrichtlinie ermöglicht der Anwendung den Zugriff auf den Schlüsseltresor mit Get, Unwrap Keyund Wrap Key Berechtigungen. Die Version des Schlüssels wird aus dem Schlüssel im Entra- oder Azure-Portal abgerufen, nachdem er erstellt wurde. Wenn Sie die automatische Drehung des Schlüsseltresorschlüssels aktivieren, stellen Sie sicher, dass Sie in der Schlüsseltresorkonfiguration der App einen versionslosen Schlüsselbezeichner verwenden, bei dem keine Schlüssel-GUID am Ende des Bezeichners platziert wird (Beispiel: https://contoso.vault.azure.net/keys/data-protection).

Damit eine App mit Azure Key Vault kommunizieren und autorisieren kann, muss das Azure.Identity NuGet-Paket von der App referenziert werden.

Note

Eine Anleitung zum Hinzufügen von Paketen zu .NET-Anwendungen finden Sie in den Artikeln unter Pakete installieren und verwalten unter Workflow für die Paketnutzung (NuGet-Dokumentation). Überprüfen Sie unter NuGet.org, ob die richtige Paketversion verwendet wird.

Note

In Nicht-Produktionsumgebungen wird im vorherigen Beispiel die Authentifizierung mithilfe von DefaultAzureCredential vereinfacht. Dabei werden Anmeldeinformationen kombiniert, die sowohl in Azure-Hostingumgebungen als auch in der lokalen Entwicklung verwendet werden, während Apps entwickelt werden, die in Azure bereitgestellt werden. Weitere Informationen finden Sie unter Authentifizieren von von Azure gehosteten .NET-Apps für Azure-Ressourcen mithilfe einer vom System zugewiesenen verwalteten Identität.

Wenn die App die älteren Azure-Pakete (Microsoft.AspNetCore.DataProtection.AzureStorage und Microsoft.AspNetCore.DataProtection.AzureKeyVault) verwendet, empfehlen wir, diese Verweise zu entfernen und auf die Azure.Extensions.AspNetCore.DataProtection.Blobs Pakete Azure.Extensions.AspNetCore.DataProtection.Keys zu aktualisieren. Die neueren Pakete behandeln wichtige Sicherheits- und Stabilitätsprobleme.

Alternative SAS-Ansatz für Shared-Access-Signaturen: Als Alternative zur Verwendung eines verwalteten Identity, um auf den Schlüssel-Blob in Azure Blob Storage zuzugreifen, können Sie die PersistKeysToAzureBlobStorage-Überladung aufrufen, die eine Blob-URI mit einem SAS-Token akzeptiert. Das folgende Beispiel verwendet weiterhin entweder ein ManagedIdentityCredential (Produktion) oder ein DefaultAzureCredential (Entwicklung und Test) für sein TokenCredential, wie im vorhergehenden Beispiel zu sehen ist:

services.AddDataProtection()
    .SetApplicationName("{APPLICATION NAME}")
    .PersistKeysToAzureBlobStorage(new Uri("{BLOB URI WITH SAS}"))
    .ProtectKeysWithAzureKeyVault(new Uri("{KEY IDENTIFIER}"), credential);

{APPLICATION NAME}: SetApplicationName legt den eindeutigen Namen dieser App im Datenschutzsystem fest. Der Wert sollte für alle Bereitstellungen der App übereinstimmen.

{BLOB URI WITH SAS}: Der vollständige URI, in dem die Schlüsseldatei mit dem SAS-Token als Abfragezeichenfolgenparameter gespeichert werden soll. Der URI wird von Azure Storage generiert, wenn Sie eine SAS für die hochgeladene Schlüsseldatei anfordern.

{KEY IDENTIFIER}: Azure Key Vault-Schlüsselbezeichner, der für die Schlüsselverschlüsselung verwendet wird. Eine Zugriffsrichtlinie ermöglicht der Anwendung den Zugriff auf den Schlüsseltresor mit Get, Unwrap Keyund Wrap Key Berechtigungen. Die Version des Schlüssels wird aus dem Schlüssel im Entra- oder Azure-Portal abgerufen, nachdem er erstellt wurde. Wenn Sie die automatische Drehung des Schlüsseltresorschlüssels aktivieren, stellen Sie sicher, dass Sie in der Schlüsseltresorkonfiguration der App einen versionslosen Schlüsselbezeichner verwenden, bei dem keine Schlüssel-GUID am Ende des Bezeichners platziert wird (Beispiel: https://contoso.vault.azure.net/keys/data-protection).

Schlüssel im Dateisystem speichern („PersistKeysToFileSystem“)

Um Schlüssel auf einer UNC-Freigabe statt am Standardspeicherort %LOCALAPPDATA% zu speichern, konfigurieren Sie das System mit PersistKeysToFileSystem:

public void ConfigureServices(IServiceCollection services)
{
    services.AddDataProtection()
        .PersistKeysToFileSystem(new DirectoryInfo(@"\\server\share\directory\"));
}

Warning

Wenn Sie den Schlüsselpersistenzspeicherort ändern, verschlüsselt das System ruhende Schlüssel nicht mehr automatisch, da es nicht weiß, ob DPAPI ein geeigneter Verschlüsselungsmechanismus ist.

Beibehalten von Schlüsseln in einer Datenbank (PersistKeysToDbContext)

Um Schlüssel in einer Datenbank mit EntityFramework zu speichern, konfigurieren Sie das System mit dem Paket Microsoft.AspNetCore.DataProtection.EntityFrameworkCore:

public void ConfigureServices(IServiceCollection services)
{
    services.AddDataProtection()
        .PersistKeysToDbContext<DbContext>()
}

Der vorangehende Code speichert die Schlüssel in der konfigurierten Datenbank. Der verwendete Datenbankkontext muss IDataProtectionKeyContext implementieren. IDataProtectionKeyContext macht die DataProtectionKeys-Eigenschaft verfügbar.

public DbSet<DataProtectionKey> DataProtectionKeys { get; set; }

Diese Eigenschaft stellt die Tabelle dar, in der die Schlüssel gespeichert werden. Erstellen Sie die Tabelle manuell oder mithilfe von DbContext-Migrationen. Weitere Informationen finden Sie unter DataProtectionKey.

Schützen der Schlüsselkonfiguration-API („ProtectKeysWith\*“)

Sie können das System so konfigurieren, dass ruhende Schlüssel geschützt werden, indem Sie eine der ProtectKeysWith\* Konfigurations-APIs aufrufen. Im folgenden Beispiel werden die Schlüssel auf einer UNC-Freigabe gespeichert, und diese ruhenden Schlüssel werden mit einem bestimmten X.509-Zertifikat verschlüsselt:

public void ConfigureServices(IServiceCollection services)
{
    services.AddDataProtection()
        .PersistKeysToFileSystem(new DirectoryInfo(@"\\server\share\directory\"))
        .ProtectKeysWithCertificate(Configuration["Thumbprint"]);
}

Sie können für X509Certificate2 ein ProtectKeysWithCertificate angeben, z. B. ein Zertifikat, das aus einer Datei geladen wurde:

public void ConfigureServices(IServiceCollection services)
{
    services.AddDataProtection()
        .PersistKeysToFileSystem(new DirectoryInfo(@"\\server\share\directory\"))
        .ProtectKeysWithCertificate(
            new X509Certificate2("certificate.pfx", Configuration["Thumbprint"]));
}

Weitere Beispiele und Erläuterungen zu den integrierten Schlüsselverschlüsselungsmechanismen finden Sie unter Schlüsselverschlüsselung in Windows und Azure mit ASP.NET Core.

Aufheben des Schutzes von Schlüsseln mit einem beliebigen Zertifikat (UnprotectKeysWithAnyCertificate)

Sie können Zertifikate rotieren und ruhende Schlüssel entschlüsseln, indem Sie ein Array von X509Certificate2-Zertifikaten mit UnprotectKeysWithAnyCertificate verwenden:

public void ConfigureServices(IServiceCollection services)
{
    services.AddDataProtection()
        .PersistKeysToFileSystem(new DirectoryInfo(@"\\server\share\directory\"))
        .ProtectKeysWithCertificate(
            new X509Certificate2("certificate.pfx", Configuration["MyPasswordKey"));
        .UnprotectKeysWithAnyCertificate(
            new X509Certificate2("certificate_old_1.pfx", Configuration["MyPasswordKey_1"]),
            new X509Certificate2("certificate_old_2.pfx", Configuration["MyPasswordKey_2"]));
}

Festlegen der Standardschlüssellebensdauer (SetDefaultKeyLifetime)

Verwenden Sie SetDefaultKeyLifetime, um das System für die Verwendung einer Schlüssellebensdauer von 14 Tagen anstelle der Standarddauer von 90 Tagen zu konfigurieren:

public void ConfigureServices(IServiceCollection services)
{
    services.AddDataProtection()
        .SetDefaultKeyLifetime(TimeSpan.FromDays(14));
}

Festlegen des Anwendungsnamens (SetApplicationName)

Standardmäßig isoliert das Datenschutzsystem Apps basierend auf ihren Inhaltsstammpfaden voneinander, auch wenn sie dasselbe physische Schlüsselrepository verwenden. Diese Isolation verhindert, dass die Apps die geschützten Nutzdaten anderer Apps verstehen.

So nutzen Sie geschützte Nutzdaten gemeinsam für Apps

  • Konfigurieren Sie SetApplicationName in jeder App mit demselben Wert.
  • Verwenden Sie für alle Apps dieselbe Version des Datenschutz-API-Stapels. Führen Sie eine der folgenden Aktionen in den Projektdateien der Apps aus:
public void ConfigureServices(IServiceCollection services)
{
    services.AddDataProtection()
        .SetApplicationName("{APPLICATION NAME}");
}

SetApplicationName legt den DataProtectionOptions.ApplicationDiscriminator intern fest. Weitere Informationen zur Verwendung des Diskriminators finden Sie in den folgenden Abschnitten weiter unten in diesem Artikel:

Automatische Schlüsselgenerierung deaktivieren (DisableAutomaticKeyGeneration)

Möglicherweise möchten Sie in Ihrem Szenario nicht, dass eine App Schlüssel automatisch rotiert (neue Schlüssel erstellt), wenn diese demnächst ablaufen. Ein Beispiel für dieses Szenario sind Apps, die in einer hierarchischen Beziehung (primär/sekundär) eingerichtet wurden, bei der nur die primäre App für Schlüsselverwaltungsaspekte verantwortlich ist und sekundäre Apps lediglich über eine schreibgeschützte Ansicht des Schlüsselrings verfügen. Die sekundären Apps können so konfiguriert werden, dass der Schlüsselring als schreibgeschützt behandelt wird, indem das System mit DisableAutomaticKeyGeneration konfiguriert wird:

public void ConfigureServices(IServiceCollection services)
{
    services.AddDataProtection()
        .DisableAutomaticKeyGeneration();
}

Isolation pro Anwendung

Wenn das Datenschutzsystem von einem ASP.NET Core-Host bereitgestellt wird, isoliert es Apps automatisch voneinander, auch wenn diese Apps unter demselben Workerprozesskonto ausgeführt werden und dasselbe Hauptschlüsselmaterial verwenden. Dies ähnelt dem IsolateApps-Modifizierer aus dem <machineKey>-Element von „System.Web“.

Der Isolationsmechanismus betrachtet jede App auf dem lokalen Computer als eindeutigen Mandanten, sodass der IDataProtector als Stamm für jede App automatisch die App-ID als Diskriminator enthält (ApplicationDiscriminator). Die eindeutige ID der App ist ihr physischer Pfad:

  • Bei in IIS gehosteten Apps ist die eindeutige ID der physische IIS-Pfad der App. Wenn eine App in einer Webfarmumgebung bereitgestellt wird, ist dieser Wert unveränderlich, sofern die IIS-Umgebungen auf allen Computern in der Webfarm gleich konfiguriert sind.
  • Bei selbstgehosteten Apps, die auf dem Kestrel-Server ausgeführt werden, ist die eindeutige ID der physische Pfad zur App auf dem Datenträger.

Der eindeutige Bezeichner ist so konzipiert, dass er beim Zurücksetzen beibehalten wird – sowohl für die einzelne App als auch für den Computer selbst.

Bei diesem Isolationsmechanismus wird davon ausgegangen, dass die Apps nicht böswillig sind. Eine böswillige App kann sich immer auf jede andere App auswirken, die unter demselben Workerprozesskonto ausgeführt wird. In einer gemeinsam genutzten Hostingumgebung, in der Apps gegenseitig nicht vertrauenswürdig sind, sollte der Hostinganbieter Maßnahmen ergreifen, um die Isolation zwischen Apps auf Betriebssystemebene sicherzustellen. Dies schließt auch die Trennung der zugrunde liegenden Schlüsselrepositorys der Apps ein.

Wenn das Datenschutzsystem nicht von einem ASP.NET Core-Host bereitgestellt wird (z. B. wenn Sie ihn über den konkreten Typ DataProtectionProvider instanziieren), ist die App-Isolation standardmäßig deaktiviert. Wenn die App-Isolation deaktiviert ist, können alle Apps, die dasselbe Schlüsselmaterial verwenden, Nutzdaten gemeinsam nutzen, solange sie die entsprechenden Zwecke bereitstellen. Um in einer solchen Umgebung App-Isolation bereitzustellen, rufen Sie die SetApplicationName-Methode für das Konfigurationsobjekt auf und geben einen eindeutigen Namen für jede App an.

Datenschutz und App-Isolation

Berücksichtigen Sie die folgenden Punkte bei der App-Isolation:

  • Wenn mehrere Apps auf dasselbe Schlüsselrepository verweisen, wird beabsichtigt, dass die Apps dasselbe Hauptschlüsselmaterial gemeinsam nutzen. Datenschutz wird unter der Annahme entwickelt, dass alle Apps, die einen Schlüsselring teilen, auf alle Elemente in diesem Schlüsselring zugreifen können. Der eindeutige Bezeichner der Anwendung wird verwendet, um anwendungsspezifische Schlüssel zu isolieren, die von den bereitgestellten Schlüsseln des Schlüsselrings abgeleitet werden. Es wird nicht erwartet, dass Berechtigungen auf Elementebene, wie sie z. B. von Azure KeyVault bereitgestellt werden, verwendet werden, um eine zusätzliche Isolation zu erzwingen. Beim Versuch, Berechtigungen auf Elementebene zu verwenden, werden Anwendungsfehler generiert. Wenn Sie sich nicht auf die integrierte Anwendungsisolation verlassen möchten, sollten Sie separate Schlüsselspeicherorte verwenden, die nicht von Anwendungen gemeinsam genutzt werden.

  • Der Anwendungsdiskriminator (ApplicationDiscriminator) wird verwendet, um verschiedenen Apps zu ermöglichen, dasselbe Hauptschlüsselmaterial gemeinsam zu nutzen, ihre kryptografischen Nutzdaten jedoch voneinander getrennt zu halten. Damit die Apps die kryptografischen Nutzdaten der jeweils anderen lesen können, müssen sie über denselben Anwendungsdiskriminator verfügen, der durch Aufrufen von SetApplicationName festgelegt werden kann.

  • Wenn eine App kompromittiert wurde (z. B. durch einen RCE-Angriff), muss das gesamte Hauptschlüsselmaterial, auf das diese App zugreifen kann, ebenfalls als kompromittiert angesehen werden, unabhängig vom Schutzstatus im Ruhezustand. Dies bedeutet auch, dass, wenn zwei Apps auf dasselbe Repository zeigen, eine Kompromittierung von einer funktional einer Kompromittierung von beiden entspricht, selbst wenn sie unterschiedliche App-Diskriminatoren verwenden.

    Diese Klausel, die "in funktionaler Hinsicht einem Kompromiss beider gleichwertig ist", gilt auch dann, wenn die beiden Apps unterschiedliche Mechanismen zum Schutz der Schlüssel im Ruhezustand verwenden. Dies ist in der Regel keine zu erwartende Konfiguration. Der Mechanismus für den Schutz ruhender Daten soll Schutz bieten, wenn ein Cyberangreifer Lesezugriff auf das Repository erhält. Cyber-Angreifende, die Schreibzugriff auf das Repository erlangen (z. B. indem sie die Codeausführungsberechtigung innerhalb einer App erhalten haben), können bösartige Schlüssel in den Speicher einfügen. Das Datenschutzsystem bietet absichtlich keinen Schutz vor Cyber-Angreifer*innen, die Schreibzugriff auf das Schlüsselrepository erlangen.

  • Wenn Apps wirklich isoliert voneinander bleiben müssen, sollten sie unterschiedliche Schlüsselrepositorys verwenden. Dies liegt natürlich außerhalb der Definition von „isoliert“. Apps sind nicht isoliert, wenn sie alle über Lese- und Schreibzugriff auf die Datenspeicher der anderen verfügen.

Ändern von Algorithmen mit UseCryptographicAlgorithms

Mit dem Datenschutzstapel können Sie den Standardalgorithmus ändern, der von neu generierten Schlüsseln verwendet wird. Die einfachste Möglichkeit besteht darin, im Konfigurationsrückruf UseCryptographicAlgorithms aufzurufen:

services.AddDataProtection()
    .UseCryptographicAlgorithms(
        new AuthenticatedEncryptorConfiguration()
    {
        EncryptionAlgorithm = EncryptionAlgorithm.AES_256_CBC,
        ValidationAlgorithm = ValidationAlgorithm.HMACSHA256
    });

Der Standardverschlüsselungsalgorithmus ist AES-256-CBC, und der Standardüberprüfungsalgorithmus ist HMACSHA256. Die Standardrichtlinie kann von Systemadministrator*innen über eine computerweite Richtlinie festgelegt werden, aber ein expliziter Aufruf von UseCryptographicAlgorithms setzt die Standardrichtlinie außer Kraft.

Durch Aufrufen von UseCryptographicAlgorithms können Sie den gewünschten Algorithmus aus einer vordefinierten Liste integrierter Algorithmen angeben. Um die Implementierungsdetails des Algorithmus müssen Sie sich nicht kümmern. Im obigen Szenario versucht das Datenschutzsystem, bei einer Ausführung unter Windows die CNG-Implementierung von AES zu verwenden. Andernfalls greift es auf die verwaltete System.Security.Cryptography.Aes-Klasse zurück.

Sie können eine Implementierung manuell über einen Aufruf von UseCustomCryptographicAlgorithms angeben.

Tip

Das Ändern von Algorithmen wirkt sich nicht auf vorhandene Schlüssel im Schlüsselring aus. Dies wirkt sich nur auf neu generierte Schlüssel aus.

Festlegen benutzerdefinierter verwalteter Algorithmen

Um benutzerdefinierte verwaltete Algorithmen anzugeben, erstellen Sie eine Instanz von ManagedAuthenticatedEncryptorConfiguration, die auf die Implementierungstypen verweist:

serviceCollection.AddDataProtection()
    .UseCustomCryptographicAlgorithms(
        new ManagedAuthenticatedEncryptorConfiguration()
    {
        // A type that subclasses SymmetricAlgorithm
        EncryptionAlgorithmType = typeof(Aes),

        // Specified in bits
        EncryptionAlgorithmKeySize = 256,

        // A type that subclasses KeyedHashAlgorithm
        ValidationAlgorithmType = typeof(HMACSHA256)
    });

Im Allgemeinen müssen die *Type-Eigenschaften auf konkrete, instanziierbare (über einen öffentlichen parameterlosen ctor) Implementierungen von SymmetricAlgorithm und KeyedHashAlgorithm verweisen, wobei die Sonderfälle im System einige Werte wie z. B typeof(Aes) zur Vereinfachung aufweisen.

Note

Ein SymmetricAlgorithm muss eine Schlüssellänge von ≥ 128 Bit und eine Blockgröße von ≥ 64 Bit aufweisen und die Verschlüsselung im CBC-Modus mit PKCS #7-Auffüllung unterstützen. Der KeyedHashAlgorithm muss eine Hashgröße von >= 128 Bit aufweisen und Schlüssel mit einer Länge unterstützen, die der Hashlänge des Hashalgorithmus entspricht. KeyedHashAlgorithm muss nicht unbedingt HMAC sein.

Angeben benutzerdefinierter Windows-CNG-Algorithmen

Um einen benutzerdefinierten Windows-CNG-Algorithmus mithilfe der Verschlüsselung im CBC-Modus mit HMAC-Validierung anzugeben, erstellen Sie eine Instanz von CngCbcAuthenticatedEncryptorConfiguration, die die Algorithmusinformationen enthält:

services.AddDataProtection()
    .UseCustomCryptographicAlgorithms(
        new CngCbcAuthenticatedEncryptorConfiguration()
    {
        // Passed to BCryptOpenAlgorithmProvider
        EncryptionAlgorithm = "AES",
        EncryptionAlgorithmProvider = null,

        // Specified in bits
        EncryptionAlgorithmKeySize = 256,

        // Passed to BCryptOpenAlgorithmProvider
        HashAlgorithm = "SHA256",
        HashAlgorithmProvider = null
    });

Note

Der symmetrische Blockchiffre-Algorithmus muss eine Schlüssellänge von >= 128 Bit und eine Blockgröße von >= 64 Bit aufweisen und die Verschlüsselung im CBC-Modus mit PKCS #7-Auffüllung unterstützen. Der Hashalgorithmus muss eine Digestgröße von >= 128 Bit aufweisen und das Öffnen mit dem Flag BCRYPT_ALG_HANDLE_HMAC_FLAG unterstützen. Die *Provider-Eigenschaften können auf NULL festgelegt werden, um den Standardanbieter für den angegebenen Algorithmus zu verwenden. Weitere Informationen finden Sie in der Dokumentation zu BCryptOpenAlgorithmProvider.

Um einen benutzerdefinierten Windows-CNG-Algorithmus mithilfe der Verschlüsselung im Galois/Counter-Modus mit Validierung anzugeben, erstellen Sie eine Instanz von CngGcmAuthenticatedEncryptorConfiguration, die die Algorithmusinformationen enthält:

services.AddDataProtection()
    .UseCustomCryptographicAlgorithms(
        new CngGcmAuthenticatedEncryptorConfiguration()
    {
        // Passed to BCryptOpenAlgorithmProvider
        EncryptionAlgorithm = "AES",
        EncryptionAlgorithmProvider = null,

        // Specified in bits
        EncryptionAlgorithmKeySize = 256
    });

Note

Der symmetrische Blockchiffre-Algorithmus muss eine Schlüssellänge von >= 128 Bit und eine Blockgröße von genau 128 Bit aufweisen und die GCM-Verschlüsselung unterstützen. Sie können die EncryptionAlgorithmProvider-Eigenschaft auf NULL festlegen, um den Standardanbieter für den angegebenen Algorithmus zu verwenden. Weitere Informationen finden Sie in der Dokumentation zu BCryptOpenAlgorithmProvider.

Angeben anderer benutzerdefinierter Algorithmen

Obwohl das Datenschutzsystem nicht als besondere API verfügbar gemacht wird, ist es erweiterbar genug, um die Angabe fast jeden Algorithmustyps zu ermöglichen. Es ist beispielsweise möglich, alle Schlüssel, die in einem Hardwaresicherheitsmodul (HSM) enthalten sind, beizubehalten und eine benutzerdefinierte Implementierung der wichtigsten Ver- und Entschlüsselungsroutinen bereitzustellen. Weitere Informationen finden Sie unter IAuthenticatedEncryptor in Kryptografieerweiterbarkeit in Core.

Beibehalten von Schlüsseln beim Hosten in einem Docker-Container

Beim Hosten in einem Docker-Container sollten Schlüssel mit einer der folgenden Optionen verwaltet werden:

Beibehalten von Schlüsseln mit Redis

Zum Speichern von Schlüsseln sollten nur Redis-Versionen verwendet werden, die Redis Data Persistence unterstützen. Azure Blob Storage ist persistent und kann zum Speichern von Schlüsseln verwendet werden. Weitere Informationen finden Sie in diesem GitHub-Issue.

Logging

Aktivieren Sie die Information oder niedrigere Protokollierungsebene, um Probleme zu diagnostizieren. Die folgende appsettings.json Datei ermöglicht die Informationsprotokollierung der Datenschutz-API:

{
  "Logging": {
    "LogLevel": {
      "Microsoft.AspNetCore.DataProtection": "Information"
    }
  }
}

Weitere Informationen zur Protokollierung finden Sie unter Protokollierung in .NET und ASP.NET Core.

Weitere Ressourcen