Nota
L'accesso a questa pagina richiede l'autorizzazione. È possibile provare ad accedere o modificare le directory.
L'accesso a questa pagina richiede l'autorizzazione. È possibile provare a modificare le directory.
TLS (Transport Layer Security) è un protocollo crittografico progettato per proteggere la comunicazione tra due computer tramite Internet. Il protocollo TLS viene esposto in .NET tramite la SslStream classe .
Questo articolo presenta le procedure consigliate per configurare la comunicazione sicura tra client e server e presuppone l'uso di .NET. Per le procedure consigliate con .NET Framework, vedere Procedure consigliate per Transport Layer Security (TLS) con .NET Framework.
Selezionare la versione TLS
Sebbene sia possibile specificare la versione del protocollo TLS da usare tramite la EnabledSslProtocols proprietà , è consigliabile rinviare le impostazioni del sistema operativo usando None il valore (impostazione predefinita).
Rinviare la decisione al sistema operativo usa automaticamente la versione più recente di TLS disponibile e consente all'applicazione di rilevare le modifiche dopo gli aggiornamenti del sistema operativo. Il sistema operativo può anche impedire l'uso di versioni TLS che non sono più considerate sicure.
Selezionare suite di crittografia
SslStream consente agli utenti di specificare quali suite di crittografia possono essere negoziate dall'handshake TLS tramite la CipherSuitesPolicy classe . Come per le versioni di TLS, è consigliabile consentire al sistema operativo di decidere con quali sono le migliori suite di crittografia con cui negoziare e, di conseguenza, è consigliabile evitare di usare CipherSuitesPolicy.
Annotazioni
CipherSuitesPolicy non è supportato su Windows e ogni tentativo di istanziarlo causerà il lancio di NotSupportedException.
Specificare un certificato locale
Quando si esegue l'autenticazione come server, SslStream è sempre necessario un certificato. Quando ci si autentica come client, si fornisce anche un certificato se il server ne richiede uno per l'autenticazione TLS reciproca (mTLS). In entrambi i ruoli, il certificato deve essere un'istanza X509Certificate2 che contiene la chiave privata.
Le versioni .NET recenti gestiscono il server e i lati client in modo simmetrico, pertanto le indicazioni seguenti applicano se l'applicazione esegue l'autenticazione come server, client o entrambi.
È possibile fornire il certificato a SslStream in diversi modi.
Quando si esegue l'autenticazione come server:
- Impostare la SslServerAuthenticationOptions.ServerCertificate proprietà o passare il certificato a SslStream.AuthenticateAsServerAsync.
- Restituisce il certificato dal SslServerAuthenticationOptions.ServerCertificateSelectionCallback callback.
- Impostare un SslStreamCertificateContext sulla proprietà SslServerAuthenticationOptions.ServerCertificateContext.
Quando si esegue l'autenticazione come client:
- Aggiungere il certificato alla SslClientAuthenticationOptions.ClientCertificates raccolta o passare una raccolta che la contiene a SslStream.AuthenticateAsClientAsync.
- Restituisci il certificato nel callback SslClientAuthenticationOptions.LocalCertificateSelectionCallback.
- Impostare un SslStreamCertificateContext nella proprietà SslClientAuthenticationOptions.ClientCertificateContext.
Annotazioni
La ClientCertificateContext proprietà è disponibile a partire da .NET 8.
Per prestazioni migliori, usare la proprietà del contesto del certificato (ServerCertificateContext o ClientCertificateContext). Quando si specifica il certificato in uno degli altri modi, SslStream crea un oggetto SslStreamCertificateContext internamente. La creazione del contesto crea un oggetto X509Chain, che è un'operazione a elevato utilizzo di CPU, quindi è più efficiente creare il contesto una sola volta e riutilizzarlo tra più SslStream istanze.
Il riutilizzo di un'istanza SslStreamCertificateContext abilita anche funzionalità aggiuntive, ad esempio la ripresa della sessione TLS nei server Linux.
Inviare certificati intermedi al peer
Quando un'autorità di certificazione intermedia rilascia il certificato locale, il peer potrebbe non essere in grado di compilare la catena di certificati completa a meno che l'handshake non includa i certificati intermedi. Per inviare questi intermedi, creare un oggetto SslStreamCertificateContext con il Create metodo e passare i certificati intermedi nel additionalCertificates parametro :
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;
Il contesto funziona allo stesso modo per entrambi i ruoli. Sul client, il contesto del certificato è il modo consigliato per inviare i certificati intermedi, perché l’alternativa — l’aggiunta dei certificati intermedi all’archivio certificati del computer o dell’utente — influisce su ogni applicazione del sistema.
Convalida personalizzata X509Certificate
Esistono alcuni scenari in cui la procedura di convalida del certificato predefinita non è adeguata e è necessaria una logica di convalida personalizzata. Le parti della logica di convalida possono essere personalizzate specificando SslClientAuthenticationOptions.CertificateChainPolicy o SslServerAuthenticationOptions.CertificateChainPolicy. In alternativa, è possibile fornire logica completamente personalizzata tramite la <proprietà System.Net.Security.SslClientAuthenticationOptions.RemoteCertificateValidationCallback> . Per altre informazioni, vedere Attendibilità dei certificati personalizzati.
Fiducia certificato personalizzata
Quando viene rilevato un certificato che non è stato emesso da alcuna autorità di certificazione attendibile dal computer (inclusi i certificati autofirmati), la procedura di convalida del certificato predefinita avrà esito negativo. Un modo possibile per risolvere questo problema consiste nell'aggiungere i certificati dell'autorità di certificazione necessari all'archivio attendibile del computer. Ciò, tuttavia, potrebbe influire su altre applicazioni nel sistema e non è sempre possibile.
La soluzione alternativa consiste nel specificare certificati radice attendibili personalizzati tramite un oggetto X509ChainPolicy. Per specificare un elenco di attendibilità personalizzato che verrà usato anziché l'elenco di attendibilità del sistema durante la convalida, considerare l'esempio seguente:
SslClientAuthenticationOptions clientOptions = new();
clientOptions.CertificateChainPolicy = new X509ChainPolicy()
{
TrustMode = X509ChainTrustMode.CustomRootTrust,
CustomTrustStore =
{
customIssuerCert
}
};
I client configurati con i criteri precedenti accettano solo certificati attendibili da customIssuerCert.
Ignorare errori di convalida specifici
Si consideri un dispositivo IoT senza un orologio permanente. Dopo l'accensione, l'orologio del dispositivo inizierebbe molti anni in passato e, pertanto, tutti i certificati sarebbero considerati "non ancora validi". Si consideri il codice seguente che mostra un'implementazione di callback di convalida ignorando le violazioni del periodo di validità.
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;
}
Pinning dei certificati
Un'altra situazione in cui è necessaria la convalida personalizzata dei certificati è quando i client prevedono che i server usino un certificato specifico o un certificato da un piccolo set di certificati noti. Questa procedura è nota come bloccaggio dei certificati. Il frammento di codice seguente mostra un callback di convalida che verifica che il server presenti un certificato con una chiave pubblica nota specifica.
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);
}
Considerazioni sulla convalida dei certificati client
Le applicazioni server devono fare attenzione quando richiedono e convalidano i certificati client. I certificati possono contenere l'estensione AIA (Authority Information Access) che specifica dove è possibile scaricare il certificato dell'autorità di certificazione. Il server può quindi tentare di scaricare il certificato emittente dal server esterno nella costruzione della X509Chain per il certificato del client. Analogamente, i server potrebbero dover contattare i server esterni per assicurarsi che il certificato client non sia stato revocato.
La necessità di contattare i server esterni durante la compilazione e la convalida del `X509Chain` potrebbe esporre l'applicazione ad attacchi di negazione del servizio se i server esterni sono lenti a rispondere. Pertanto, le applicazioni server devono configurare il comportamento di X509Chain costruzione usando CertificateChainPolicy.
Annotazioni
A partire da .NET 11, SslStream disabilita i download dei certificati AIA per impostazione predefinita quando si convalidano i certificati client come server. Se non viene specificata alcuna personalizzazione CertificateChainPolicy , il server non tenterà di recuperare i certificati intermedi mancanti tramite AIA. Per ulteriori informazioni, vedere I download dei certificati AIA lato server con SslStream sono disabilitati per impostazione predefinita.