Fehlermeldung
The remote certificate is invalid because of errors in the certificate chain: UntrustedRoot
Auch ausgegeben als
- System.Security.Authentication.AuthenticationException: The remote certificate is invalid because of errors in the certificate chain: UntrustedRoot
Die Flags nach dem Doppelpunkt stammen aus X509ChainStatusFlags und können kombiniert auftreten (zum Beispiel „UntrustedRoot, RevocationStatusUnknown“). Auch selbstsignierte Serverzertifikate melden UntrustedRoot. Unter Linux verwendet .NET OpenSSL und den CA-Speicher der Distribution, unter Windows und macOS die Zertifikatsspeicher des Systems.
.NET SslStream / HttpClient — AuthenticationException (X509ChainStatusFlags.UntrustedRoot)
Was der Fehler bedeutet
.NET hat die Zertifikatskette des Servers bis zu einem Root-Zertifikat aufgebaut, und diesem Root-Zertifikat vertraut der Zertifikatsspeicher der Plattform nicht (oder die Kette endet in einem selbstsignierten Zertifikat, dem nicht vertraut wird). Das Zertifikat selbst kann in Ordnung sein; der Rechner vertraut nur der Zertifizierungsstelle dahinter nicht. HttpClient meldet den Fehler als innere Exception von „The SSL connection could not be established“.
Warum der Fehler auftritt
Eine Firmen-CA oder private CA
häufigInterne APIs, SQL Server mit einem Zertifikat der Domain-CA oder Dienste in einer Laborumgebung verwenden Root-Zertifikate, die der Rechner (oft ein Linux-Container) nicht hat.
Ein Proxy mit TLS-Inspektion
häufigDie Kette neu signierter Verbindungen endet beim Root-Zertifikat des Proxys. Windows-Rechner haben es meist über eine Gruppenrichtlinie, Linux-Container und WSL nicht.
Ein selbstsigniertes Serverzertifikat
häufigSelbstsignierte Zertifikate (auch die von Entwicklungsservern) enden bei sich selbst und werden als UntrustedRoot gemeldet.
Dem Container-Image fehlt das Root-Zertifikat
gelegentlichEin Root-Zertifikat, das auf dem Host oder unter Windows installiert ist, gibt es nicht im Linux-Container, in dem die .NET-App läuft.
So behebst du den Fehler
- 1.
Linux: Root-Zertifikat im Zertifikatsspeicher des Systems installieren
.NET unter Linux liest den OpenSSL-Speicher, daher genügt update-ca-certificates (oder das Gegenstück der Distribution); in Containern erledigst du das im Dockerfile.
bash # Linux (incl. containers): .NET uses the OpenSSL system store sudo cp corp-root-ca.pem /usr/local/share/ca-certificates/corp-root-ca.crt sudo update-ca-certificates - 2.
Windows und macOS: dem Root-Zertifikat im Zertifikatsspeicher des Systems vertrauen
Importiere das Root-Zertifikat unter Windows nach LocalMachine\Root oder unter macOS in den Schlüsselbund „System“; .NET verwendet diese Speicher.
text # Windows (elevated PowerShell): trust the root machine-wide Import-Certificate -FilePath .\corp-root-ca.cer -CertStoreLocation Cert:\LocalMachine\Root # macOS sudo security add-trusted-cert -d -r trustRoot -k /Library/Keychains/System.keychain corp-root-ca.pem - 3.
Einem privaten Root-Zertifikat für einen einzelnen Client vertrauen
SocketsHttpHandler.SslOptions.CertificateChainPolicy mit CustomRootTrust behält die vollständige Validierung bei, verankert sie aber in deinem Root-Zertifikat. Eine eigene Richtlinie aktiviert standardmäßig die Online-Prüfung auf Widerruf, setze RevocationMode daher passend zu dem, was deine CA veröffentlicht (in unserem Test scheiterten private Zertifikate ohne CRL/OCSP mit RevocationStatusUnknown, bis NoCheck gesetzt war).
csharp // Trust one private root for this client only; chain, dates and name are still verified. var root = X509CertificateLoader.LoadCertificateFromFile("corp-root-ca.pem"); var handler = new SocketsHttpHandler(); handler.SslOptions.CertificateChainPolicy = new X509ChainPolicy { TrustMode = X509ChainTrustMode.CustomRootTrust, // a custom policy defaults to online revocation checks; use NoCheck only if the CA publishes no CRL/OCSP RevocationMode = X509RevocationMode.NoCheck, }; handler.SslOptions.CertificateChainPolicy.CustomTrustStore.Add(root); using var client = new HttpClient(handler); - 4.
Entwicklung: dem Entwicklungszertifikat von ASP.NET Core vertrauen
dotnet dev-certs https --trust installiert das Entwicklungszertifikat für localhost unter Windows und macOS und vertraut ihm (unter Linux hängt das Vertrauen von der Distribution ab).
bash # ASP.NET Core development certificate on localhost dotnet dev-certs https --trust
Verwandte Fehler
The SSL connection could not be established, see inner exception..NET HttpClientThe remote certificate is invalid because of errors in the certificate chain: P….NET SslStream / HttpClientThe remote certificate was rejected by the provided RemoteCertificateValidation….NET SslStream / HttpClientcurl: (60) SSL certificate problem: self-signed certificate in certificate chaincurl (OpenSSL backend)