Kommentar
Åtkomst till den här sidan kräver auktorisering. Du kan prova att logga in eller ändra kataloger.
Åtkomst till den här sidan kräver auktorisering. Du kan prova att ändra kataloger.
TLS (Transport Layer Security) är ett kryptografiskt protokoll som är utformat för att skydda kommunikationen mellan två datorer via Internet. TLS-protokollet exponeras i .NET via SslStream klassen.
Den här artikeln innehåller metodtips för att konfigurera säker kommunikation mellan klient och server och förutsätter användning av .NET. Metodtips för .NET Framework finns i Metodtips för Transport Layer Security (TLS) med .NET Framework.
Välj TLS-version
Även om det är möjligt att ange vilken version av TLS-protokollet som ska användas via EnabledSslProtocols-egenskapen, rekommenderar vi att du använder operativsystemets inställningar med hjälp av None-värdet (detta är standardvärdet).
Om du skjuter upp beslutet till operativsystemet används automatiskt den senaste versionen av TLS som är tillgänglig och låter programmet hämta ändringar efter OS-uppgraderingar. Operativsystemet kan också förhindra användning av TLS-versioner som inte längre anses vara säkra.
Välj chiffersviter
SslStream tillåter användare att via CipherSuitesPolicy-klassen specificera vilka chiffersviter som kan förhandlas av TLS-handskakningen. Precis som med TLS-versioner rekommenderar vi att operativsystemet bestämmer vilka som är de bästa chiffersviterna att förhandla med, och därför rekommenderar vi att du undviker att använda CipherSuitesPolicy.
Anmärkning
CipherSuitesPolicy stöds inte i Windows, och försök att instansiera det kommer att orsaka att NotSupportedException undantas.
Ange ett lokalt certifikat
När du autentiserar dig som en server kräver SslStream alltid ett certifikat. När du autentiserar som en klient anger du även ett certifikat om servern begär ett för ömsesidig TLS (mTLS). I båda rollerna måste certifikatet vara en X509Certificate2 instans som innehåller den privata nyckeln.
De senaste .NET versionerna hanterar server- och klientsidorna symmetriskt, så följande vägledning gäller om programmet autentiserar som en server, en klient eller både och.
Du kan ange certifikatet till SslStream på flera sätt.
När du autentiserar som en server:
- Ange egenskapen SslServerAuthenticationOptions.ServerCertificate eller skicka certifikatet till SslStream.AuthenticateAsServerAsync.
- Returnera certifikatet från återanropet SslServerAuthenticationOptions.ServerCertificateSelectionCallback .
- Ange en SslStreamCertificateContext på egenskapen SslServerAuthenticationOptions.ServerCertificateContext .
När du autentiserar som en klient:
- Lägg till certifikatet i SslClientAuthenticationOptions.ClientCertificates samlingen eller skicka en samling som innehåller det till SslStream.AuthenticateAsClientAsync.
- Returnera certifikatet från återanropet SslClientAuthenticationOptions.LocalCertificateSelectionCallback .
- Ange en SslStreamCertificateContext på egenskapen SslClientAuthenticationOptions.ClientCertificateContext .
Anmärkning
Egenskapen ClientCertificateContext är tillgänglig från och med .NET 8.
För bättre prestanda använder du certifikatkontextegenskapen (ServerCertificateContext eller ClientCertificateContext). När du tillhandahåller certifikatet på något av de andra sätten skapar SslStream ett SslStreamCertificateContext internt. När du skapar kontexten skapas en X509Chain, vilket är en processorintensiv åtgärd, så det är mer effektivt att skapa kontexten en gång och återanvända den över flera SslStream instanser.
Om du återanvänder en SslStreamCertificateContext instans kan du även använda extra funktioner, till exempel återupptagande av TLS-sessioner på Linux-servrar.
Skicka mellanliggande certifikat till peer
När en mellanliggande certifikatutfärdare utfärdar det lokala certifikatet kanske motparten inte kan bygga upp hela certifikatkedjan om inte TLS-handskakningen innehåller de mellanliggande certifikaten. Om du vill skicka dessa mellanliggande objekt skapar du en SslStreamCertificateContext med Create -metoden och skickar mellanliggande certifikat i parametern additionalCertificates :
X509Certificate2 leafCertificate = GetLeafCertificate();
X509Certificate2Collection intermediates = GetIntermediateCertificates();
SslStreamCertificateContext certificateContext =
SslStreamCertificateContext.Create(leafCertificate, intermediates);
// When you authenticate as a server.
serverOptions.ServerCertificateContext = certificateContext;
// When you authenticate as a client for mutual TLS.
clientOptions.ClientCertificateContext = certificateContext;
Kontexten fungerar på samma sätt för båda rollerna. På klientsidan är certifikatkontexten det rekommenderade sättet att skicka mellanliggande objekt, eftersom alternativet – att lägga till mellanliggande objekt i datorn eller användarcertifikatarkivet – påverkar varje program i systemet.
Egenvald X509Certificate validering
Det finns vissa scenarier där standardproceduren för certifikatverifiering inte är tillräcklig och viss anpassad valideringslogik krävs. Delar av valideringslogik kan anpassas genom att SslClientAuthenticationOptions.CertificateChainPolicy ange eller SslServerAuthenticationOptions.CertificateChainPolicy. Du kan också ange helt anpassad logik via <egenskapen System.Net.Security.SslClientAuthenticationOptions.RemoteCertificateValidationCallback> . Mer information finns i Anpassat certifikatförtroende.
Anpassat certifikatförtroende
När du stöter på ett certifikat som inte har utfärdats av någon av de certifikatutfärdare som är betrodda av datorn (inklusive självsignerade certifikat) misslyckas standardproceduren för certifikatverifiering. Ett möjligt sätt att lösa detta är att lägga till nödvändiga utfärdarcertifikat i datorns betrodda arkiv. Det kan dock påverka andra program i systemet och är inte alltid möjligt.
Den alternativa lösningen är att ange anpassade betrodda rotcertifikat via en X509ChainPolicy. Om du vill ange en anpassad förtroendelista som ska användas i stället för listan över systemförtroenden under valideringen bör du överväga följande exempel:
SslClientAuthenticationOptions clientOptions = new();
clientOptions.CertificateChainPolicy = new X509ChainPolicy()
{
TrustMode = X509ChainTrustMode.CustomRootTrust,
CustomTrustStore =
{
customIssuerCert
}
};
Klienter som konfigurerats med föregående princip accepterar endast certifikat som är betrodda av customIssuerCert.
Ignorera specifika verifieringsfel
Överväg en IoT-enhet utan en beständig klocka. När enheten startas börjar klockan många år tillbaka i tiden och därför anses alla certifikat vara "ännu inte giltiga". Tänk på följande kod som visar en implementering av valideringsåteranrop som ignorerar överträdelser av giltighetsperioden.
static bool CustomCertificateValidationCallback(
object sender,
X509Certificate? certificate,
X509Chain? chain,
SslPolicyErrors sslPolicyErrors)
{
// Anything that would have been accepted by default is OK
if (sslPolicyErrors == SslPolicyErrors.None)
{
return true;
}
// If there is something wrong other than a chain processing error, don't trust it.
if (sslPolicyErrors != SslPolicyErrors.RemoteCertificateChainErrors)
{
return false;
}
Debug.Assert(chain is not null);
// If the reason for RemoteCertificateChainError is that the chain built empty, don't trust it.
if (chain.ChainStatus.Length == 0)
{
return false;
}
foreach (X509ChainStatus status in chain.ChainStatus)
{
// If an error other than `NotTimeValid` (or `NoError`) is present, don't trust it.
if ((status.Status & ~X509ChainStatusFlags.NotTimeValid) != X509ChainStatusFlags.NoError)
{
return false;
}
}
return true;
}
Fäst certifikat
En annan situation där anpassad certifikatverifiering krävs är när klienter förväntar sig att servrar ska använda ett specifikt certifikat eller ett certifikat från en liten uppsättning kända certifikat. Den här metoden kallas för att fästa certifikat. Följande kodfragment visar ett verifieringsåteranrop som kontrollerar att servern visar ett certifikat med en specifik känd offentlig nyckel.
static bool CustomCertificateValidationCallback(
object sender,
X509Certificate? certificate,
X509Chain? chain,
SslPolicyErrors sslPolicyErrors)
{
// If there is something wrong other than a chain processing error, don't trust it.
if ((sslPolicyErrors & ~SslPolicyErrors.RemoteCertificateChainErrors) != 0)
{
return false;
}
Debug.Assert(certificate is not null);
const string ExpectedPublicKey =
"3082010A0282010100C204ECF88CEE04C2B3D850D57058CC9318EB5C" +
"A86849B022B5F9959EB12B2C763E6CC04B604C4CEAB2B4C00F80B6B0" +
"F972C98602F95C415D132B7F71C44BBCE9942E5037A6671C618CF641" +
"42C546D31687279F74EB0A9D11522621736C844C7955E4D16BE8063D" +
"481552ADB328DBAAFF6EFF60954A776B39F124D131B6DD4DC0C4FC53" +
"B96D42ADB57CFEAEF515D23348E72271C7C2147A6C28EA374ADFEA6C" +
"B572B47E5AA216DC69B15744DB0A12ABDEC30F47745C4122E19AF91B" +
"93E6AD2206292EB1BA491C0C279EA3FB8BF7407200AC9208D98C5784" +
"538105CBE6FE6B5498402785C710BB7370EF6918410745557CF9643F" +
"3D2CC3A97CEB931A4C86D1CA850203010001";
return certificate.GetPublicKeyString().Equals(ExpectedPublicKey);
}
Överväganden för validering av klientcertifikat
Serverprogram måste vara försiktiga när de kräver och validerar klientcertifikat. Certifikat kan innehålla tillägget AIA (Authority Information Access) som anger var utfärdarcertifikatet kan laddas ned. Servern kan därför försöka ladda ned utfärdarcertifikatet från den externa servern när du skapar X509Chain för klientcertifikatet. På samma sätt kan servrar behöva kontakta externa servrar för att säkerställa att klientcertifikatet inte har återkallats.
Behovet av att kontakta externa servrar när du skapar och verifierar X509Chain kan göra programmet utsatt för överbelastningsattacker om de externa servrarna svarar långsamt. Därför bör serverapplikationer konfigurera X509Chain byggebeteendet med hjälp av CertificateChainPolicy.
Anmärkning
Från och med .NET 11 inaktiverar SslStream AIA-certifikatnedladdningar som standard när en server verifierar klientcertifikat. Om ingen anpassad CertificateChainPolicy har angetts försöker servern inte hämta saknade mellanliggande certifikat via AIA. Mer information finns i SslStream-AIA-certifikatnedladdningar på serversidan inaktiverade som standard.