Cenni preliminari sulla crittografia

Aggiornamento: novembre 2007

La crittografia consente di proteggere i dati dalla visualizzazione non autorizzata e di rilevare se sono stati modificati e offre un mezzo di comunicazione sicuro da utilizzare in alternativa ai canali non sicuri. I dati, ad esempio, possono essere crittografati mediante un algoritmo di crittografia, trasmessi nello stato crittografato e, successivamente, decrittografati dalla persona a cui sono destinati. Se una terza parte intercetta i dati crittografati, troverà molte difficoltà a decifrarli.

In questa panoramica vengono riepilogati i metodi e le procedure di crittografia supportati da .NET Framework, incluso il supporto per manifesti ClickOnce, Suite B e Cryptography Next Generation (CNG) fornito da .NET Framework versione 3.5. Di seguito sono elencate le diverse sezioni di questa panoramica:

  • Primitive di crittografia

  • Crittografia a chiave segreta

  • Crittografia a chiave pubblica

  • Firme digitali

  • Valori hash

  • Generazione di numeri casuali

  • Manifesti ClickOnce

  • Supporto per Suite B

  • Classi Cryptography Next Generation (CNG)

Per ulteriori informazioni sulla crittografia e sui servizi, i componenti e gli strumenti Microsoft che consentono di rendere sicure le applicazioni tramite la crittografia, vedere la sezione della presente documentazione dedicata alla sicurezza nello sviluppo Win32 e COM.

Primitive di crittografia

In una situazione tipica in cui viene utilizzata la crittografia, due parti, Alice e Bob, comunicano su un canale non sicuro. Essi desiderano che la loro comunicazione non venga compresa da chiunque li stia ascoltando. Inoltre, dal momento che non si trovano nello stesso posto, Alice deve assicurarsi che le informazioni ricevute da Bob non siano state modificate da altre persone durante la trasmissione e che siano state inviate effettivamente da Bob e non da qualcuno che finge di essere Bob.

La crittografia viene quindi utilizzata per raggiungere i seguenti obiettivi:

  • Confidenzialità: proteggere da letture non autorizzate l'identità o i dati di un utente.

  • Integrità dei dati: proteggere i dati da possibili modifiche.

  • Autenticazione: garantire che i dati provengano da una determinata fonte.

  • Non ripudio: per impedire a una determinata parte di negare di aver inviato un messaggio.

Per raggiungere questi obiettivi, è possibile utilizzare una combinazione di algoritmi e operazioni note come primitive di crittografia per creare uno schema di crittografia. Nella tabella che segue sono riportate le primitive di crittografia e il relativo impiego.

Primitiva di crittografia

Utilizzo

Crittografia a chiave segreta (crittografia simmetrica)

I dati vengono trasformati in modo che non possano essere letti da terze parti. Questo tipo di crittografia utilizza una chiave segreta a singola condivisione per crittografare e decrittografare i dati.

Crittografia a chiave pubblica (crittografia asimmetrica)

I dati vengono trasformati in modo che non possano essere letti da terze parti. Questo tipo di crittografia utilizza una coppia di chiavi pubblica/privata per crittografare e decrittografare i dati.

Firma di crittografia

Consente di verificare che i dati provengano da una determinata persona attraverso la creazione di una firma digitale che sia univoca sono per quella persona. Questo processo utilizza anche le funzioni hash.

Hash di crittografia

Associa dati di qualsiasi lunghezza a una sequenza di dati a lunghezza fissa. Gli hash sono statisticamente univoci. La stessa sequenza a due byte, ma inviata in due istanti differenti, non avrà un hash sullo stesso valore.

Crittografia a chiave segreta

Negli algoritmi di crittografia a chiave segreta viene utilizzata una singola chiave segreta per crittografare e decrittografare i dati. È necessario proteggere la chiave dall'accesso di agenti non autorizzati in quanto chiunque sia in possesso della chiave può utilizzarla per decrittografare i dati o crittografare i propri dati così che sembrino essere stati originati dall'utente proprietario della chiave.

La crittografia a chiave segreta viene definita anche crittografia simmetrica in quanto la stessa chiave viene utilizzata sia per la crittografia che per la decrittografia. Gli algoritmi di crittografia a chiave segreta sono estremamente veloci rispetto a quelli a chiave pubblica e si prestano particolarmente all'esecuzione di trasformazioni di crittografia su flussi di dati di grandi dimensioni. Esiste un limite a livello matematico per la quantità di dati che è possibile crittografare mediante gli algoritmi di crittografia asimmetrici, ad esempio RSA. Gli algoritmi di crittografia simmetrici non presentano in genere questi problemi:

Un tipo di algoritmo a chiave segreta, denominato crittografia a blocchi, viene utilizzato per crittografare un blocco di dati alla volta. Gli algoritmi di crittografia a blocchi, quali Data Encryption Standard (DES), TripleDES e Advanced Encryption Standard (AES), trasformano a livello di crittografia un blocco di input di n byte in un blocco di output di byte crittografati. Per crittografare o decrittografare una sequenza di byte, è necessario procedere blocco per blocco. Poiché la dimensione di n è limitata (8 byte per DES e TripleDES, 16 byte come valore predefinito o 24 o 32 byte per AES), i valori di dati superiori a n devono essere crittografati suddividendo i dati in blocchi. I valori di dati inferiori a n devono essere espansi a n per essere elaborati.

Una forma semplice di crittografia a blocchi è nota come modalità ECB (Electronic Codebook). La modalità ECB non è considerata sicura poiché non prevede l'utilizzo di un vettore di inizializzazione per inizializzare il primo blocco di testo non crittografato. Per una determinata chiave segreta k, tramite una semplice crittografia a blocchi in cui non viene utilizzato un vettore di inizializzazione lo stesso blocco di input di testo non crittografato verrà crittografato nello stesso blocco di output di testo crittografato. Se pertanto sono presenti blocchi doppi all'interno del flusso di input di testo non crittografato, si avranno blocchi doppi all'interno del flusso di output di testo crittografato. Questi blocchi di output doppi segnalano agli utenti non autorizzati che la crittografia è vulnerabile fornendo indicazioni sugli algoritmi che possono essere stati utilizzati e sulle possibili modalità di attacco. La modalità di crittografia ECB è pertanto piuttosto vulnerabile all'analisi e, in definitiva, all'individuazione delle chiavi.

Le classi di crittografia a blocchi fornite nella libreria di classi di base si servono di un modello di concatenazione predefinito denominato CBC (Cipher Block Chaining), benché sia possibile modificare questa impostazione predefinita.

La crittografia CBC consente di superare i problemi associati alla crittografia ECB utilizzando un vettore di inizializzazione (IV) per crittografare il primo blocco di testo non crittografato. Ogni successivo blocco di testo non crittografato viene sottoposto a un'operazione OR esclusiva (XOR) bit per bit con il blocco di testo crittografato precedente prima di essere crittografato. Ogni blocco di testo crittografato è pertanto dipendente da tutti i blocchi precedenti. Attraverso questo sistema, anche se le intestazioni dei messaggi più comuni sono note a un utente non autorizzato, non possono essere utilizzate per decodificare una chiave.

Un modo per compromettere i dati crittografati con la crittografia CBC consiste nell'eseguire una ricerca approfondita di ogni possibile chiave. A seconda della dimensione della chiave utilizzata per la crittografia, questo tipo di ricerca richiede tempi di esecuzione estremamente lunghi anche sui computer più veloci e risulta pertanto non fattibile. Dimensioni di chiavi maggiori sono più difficili da decifrare. Sebbene a livello teorico non sia impossibile il recupero dei dati crittografati da parte di utenti non autorizzati, questa operazione viene resa estremamente complicata dalla crittografia. Se sono necessari tre mesi per eseguire una ricerca approfondita per recuperare dati validi solo per alcuni giorni, tale metodo non è praticabile.

La crittografia a chiave segreta presenta lo svantaggio di presupporre che due parti abbiano concordato l'utilizzo di una chiave e di un vettore di inizializzazione e che si siano comunicati reciprocamente i valori. Il vettore di inizializzazione non è considerato segreto e può essere trasmesso come testo non crittografato in un messaggio. È necessario tuttavia che la chiave sia mantenuta segreta agli utenti non autorizzati. A causa di questi problemi, la crittografia a chiave segreta viene spesso utilizzata in combinazione con la crittografia a chiave pubblica per comunicare in privato i valori della chiave e del vettore di inizializzazione.

Si supponga che Alice e Bob abbiano l'esigenza di comunicare su un canale non sicuro. Per utilizzare la crittografia a chiave segreta, Alice e Bob accettano di utilizzare un determinato algoritmo (ad esempio AES) con una chiave e un vettore di inizializzazione specifici. Alice crea un messaggio e un flusso di rete (ad esempio una named pipe o un messaggio di posta elettronica di rete) in cui invia il messaggio. Quindi crittografa il testo utilizzando la chiave e il vettore di inizializzazione e invia il messaggio crittografato e il vettore di inizializzazione a Bob tramite Internet. Bob riceve il testo crittografato e lo decrittografa utilizzando il vettore di inizializzazione e la chiave precedentemente concordata. Se la trasmissione viene intercettata, l'intercettatore non è in grado di recuperare il messaggio originale in quanto non conosce la chiave. In questo scenario, solo la chiave deve rimanere segreta. In uno scenario reale Alice o Bob genera una chiave segreta e utilizza la crittografia a chiave pubblica (asimmetrica) per trasferire la chiave segreta (simmetrica) all'altra parte. Per ulteriori informazioni sulla crittografia a chiave pubblica, vedere la sezione successiva.

In .NET Framework sono disponibili le seguenti classi che implementano gli algoritmi della crittografia a chiave segreta:

Crittografia a chiave pubblica

La crittografia a chiave pubblica utilizza una chiave privata che deve essere tenuta segreta agli utenti non autorizzati e una chiave pubblica che può essere resa pubblica a tutti. La chiave pubblica e la chiave privata sono collegate matematicamente. I dati crittografati con la chiave pubblica possono essere decrittografati solo con la chiave privata e i dati firmati con la chiave privata possono essere verificati solo con la chiave pubblica. La chiave pubblica può essere distribuita a tutti in quanto viene utilizzata per crittografare i dati da inviare a chi detiene la chiave privata. Gli algoritmi di crittografia a chiave pubblica sono noti anche come algoritmi asimmetrici, in quanto per crittografare e successivamente decrittografare i dati è necessario utilizzare due chiavi diverse. Una regola di crittografia di base proibisce il riutilizzo di chiavi ed entrambe le chiavi devono essere univoche per ogni sessione di comunicazione. Tuttavia, in pratica, chiavi asimmetriche hanno in genere una durata estesa.

Le due parti, Alice e Bob, possono utilizzare la crittografia a chiave pubblica nel modo descritto di seguito. Alice genera innanzitutto una coppia di chiavi pubblica/privata. Se Bob desidera inviare a Alice un messaggio crittografato, le chiede la chiave pubblica. Alice invia a Bob la chiave pubblica su una rete non sicura e Bob la utilizza per crittografare un messaggio. Bob invia il messaggio crittografato a Alice, la quale lo decrittografa utilizzando la sua chiave privata. Se Bob ha ricevuto la chiave di Alice su un canale non sicuro, ad esempio una rete pubblica, è esposto a un attacco di tipo man-in-the-middle. Bob, pertanto, deve verificare con Alice di disporre della copia corretta della sua chiave pubblica.

Durante la trasmissione della chiave pubblica di Alice, una persona non autorizzata potrebbe intercettare la chiave e il messaggio crittografato da Bob. Non è comunque in grado di decrittografare il messaggio con la chiave pubblica. Il messaggio può essere decrittografato solo con la chiave privata di Alice che non è stata trasmessa. Alice non utilizza la propria chiave privata per crittografare un messaggio di risposta a Bob in quanto chiunque sia in possesso della chiave pubblica potrebbe decrittografare il messaggio. Se Alice desidera inviare un messaggio a Bob, gli chiede la chiave pubblica e crittografa il suo messaggio utilizzando quella chiave. Bob decrittografa il messaggio utilizzando la sua chiave privata associata.

In questo scenario Alice e Bob utilizzano la crittografia a chiave pubblica (asimmetrica) per trasferire una chiave segreta (simmetrica) e utilizzano la crittografia a chiave segreta per il resto della sessione.

Nell'elenco seguente viene illustrato il confronto tra algoritmi di crittografia a chiave pubblica e a chiave segreta:

  • Negli algoritmi di crittografia a chiave pubblica viene utilizzata una dimensione del buffer fissa, mentre in quelli di crittografia a chiave segreta viene utilizzato un buffer di lunghezza variabile.

  • Gli algoritmi a chiave pubblica non possono essere utilizzati per concatenare i dati in flussi allo stesso modo degli algoritmi a chiave segreta in quanto è possibile crittografare solo piccole quantità di dati. Pertanto le operazioni asimmetriche non utilizzano lo stesso modello di flusso delle operazioni simmetriche.

  • La crittografia a chiave pubblica ha uno spazio delle chiavi (intervallo dei valori possibili) molto più ampio rispetto alla crittografia a chiave segreta, pertanto è meno esposta a tecniche esaustive per scoprire la chiave.

  • Le chiavi pubbliche sono facili da distribuire poiché non è necessario proteggerle, purché sia possibile verificare l'identità del mittente.

  • Alcuni algoritmi a chiave pubblica, ad esempio RSA e DSA, ma non Diffie-Hellman, possono essere utilizzati per creare firme digitali per la verifica dell'identità del mittente dei dati.

  • Gli algoritmi a chiave pubblica sono molto lenti rispetto a quelli a chiave segreta e non sono destinati alla crittografia di grandi quantità di dati. Essi risultano utili solo per il trasferimento di piccole quantità di dati. Generalmente la crittografia a chiave pubblica viene utilizzata per crittografare una chiave e un vettore di inizializzazione utilizzabili da un algoritmo a chiave segreta. Dopo il trasferimento della chiave e del vettore di inizializzazione, la crittografia a chiave segreta viene utilizzata per il resto della sessione.

In .NET Framework sono disponibili le seguenti classi che implementano gli algoritmi della crittografia a chiave pubblica:

RSA consente sia la crittografia sia la firma, mentre DSA può essere utilizzato solo per la firma e Diffie-Hellman solo per la generazione di chiavi. In genere, gli algoritmi a chiave pubblica sono più limitati nell'utilizzo rispetto a quelli a chiave privata.

Firme digitali

Gli algoritmi a chiave pubblica possono essere utilizzati per formare firme digitali, il cui obiettivo è l'autenticazione dell'identità di un mittente, se la chiave pubblica di quest'ultimo viene considerata attendibile, e la protezione dell'integrità dei dati. Attraverso una chiave pubblica generata da Alice, il destinatario dei suoi dati può verificare che siano stati inviati effettivamente da lei confrontando la firma digitale sui dati e la chiave pubblica di Alice.

Per apporre una firma digitale a un messaggio utilizzando la crittografia a chiave pubblica, Alice applica dapprima un algoritmo hash al messaggio per creare un digest del messaggio. Il digest è una rappresentazione dei dati compatta e univoca. Alice quindi crittografa il digest del messaggio con la sua chiave privata per creare la sua chiave personale. Alla ricezione del messaggio e della firma, Bob decrittografa la firma con la chiave pubblica di Alice per recuperare il digest del messaggio e genera un hash mediante lo stesso algoritmo hash inviato da Alice. Se il digest del messaggio calcolato da Bob corrisponde esattamente al digest del messaggio ricevuto da Alice, Bob ha la certezza che il messaggio provenga dal possessore della chiave privata e che i dati non siano stati modificati. Se Bob ha la certezza che Alice sia il possessore della chiave privata, saprà che il messaggio proviene solo da Alice.

Nota:

Chiunque può verificare una firma in quanto la chiave pubblica del mittente è di pubblico dominio e generalmente viene inclusa nel formato della firma digitale. Questo metodo non mantiene la segretezza del messaggio. Perché possa essere segreto, anche il messaggio deve essere crittografato.

In .NET Framework sono disponibili le seguenti classi che implementano gli algoritmi della firma digitale:

Valori hash

Gli algoritmi hash associano valori binari di lunghezza arbitraria a piccoli valori binari di lunghezza fissa, noti come valori hash. Per valore hash si intende una rappresentazione numerica di una porzione di dati. Se si inserisce un hash in un paragrafo di testo non crittografato e si modifica anche una sola lettera del paragrafo, un hash successivo produrrà un valore diverso. Se l'hash è basato su una crittografia avanzata, il relativo valore verrà modificato in modo significativo. Se ad esempio viene modificato un singolo bit di un messaggio, una funzione hash sicura può produrre un output che si differenzia del 50%. Molti valori di input possono avere hash dello stesso valore di output. Dal punto di vista del calcolo è tuttavia non fattibile trovare due input distinti con hash sullo stesso valore.

Due parti (Alice e Bob) sono riuscite a utilizzare una funzione hash per garantire l'integrità del messaggio. Hanno selezionato un algoritmo di hash per firmare i messaggi. Alice ha scritto un messaggio, quindi ha creato un hash di tale messaggio tramite l'algoritmo selezionato. Hanno quindi seguito uno dei metodi seguenti:

  • Alice invia il messaggio come testo normale e il messaggio con hash (firma digitale) a Bob. Bob riceve il messaggio, ne esegue l'hashing, quindi confronta il proprio valore hash con quello che ha ricevuto da Alice. Se i valori hash corrispondono, il messaggio non è stato alterato. Se invece i valori non corrispondono, il messaggio è stato alterato dopo essere stato scritto da Alice.

    Purtroppo, questo metodo non consente di stabilire l'autenticità del mittente. Chiunque può rappresentare Alice e inviare un messaggio a Bob. Possono utilizzare lo stesso algoritmo hash per firmare il messaggio e tutto ciò che Bob è in grado di determinare è che il messaggio corrisponde alla relativa firma. Si tratta di una forma di attacco di tipo man-in-the-middle. Per ulteriori informazioni, vedere Esempio di comunicazione protetta tramite Cryptography Next Generation (CNG).

  • Alice invia il messaggio come testo normale a Bob tramite un canale pubblico non protetto. Invia il messaggio con hash a Bob su un canale privato protetto. Bob riceve il messaggio in testo normale, ne esegue l'hashing, quindi confronta il valore hash con quello scambiato privatamente. Se i valori corrispondono, Bob può accertare quanto segue:

    • Il messaggio non è stato modificato.

    • Il mittente del messaggio (Alice) è autentico.

    Perché il sistema funzioni, Alice deve nascondere il valore hash originale a tutte le parti ad eccezione di Bob.

  • Alice invia il messaggio in testo normale a Bob tramite un canale pubblico non protetto e inserisce il messaggio con hash sul proprio sito Web pubblico.

    Questo metodo consente di evitare la manomissione del messaggio impedendo a chiunque di modificare il valore hash. Anche se chiunque può leggere il messaggio e il relativo hash, il valore hash può essere modificato solo da Alice. Un utente non autorizzato che desidera rappresentare Alice richiede l'accesso al sito Web di Alice.

Nessuno dei metodi precedenti impedisce la lettura dei messaggi di Alice, perché vengono trasmessi come testo normale. Una soluzione di sicurezza completa richiede le firme digitali (firma dei messaggi) e la crittografia.

In .NET Framework sono disponibili le seguenti classi che implementano gli algoritmi della firma digitale:

Nota:

I difetti di progettazione di MD5 sono stati individuati nel 1996 e SHA-1 è stato consigliato in sostituzione. Nel 2004, sono stati individuati altri difetti e l'algoritmo MD5 non è più considerato sicuro. Anche l'algoritmo SHA-1 si è rivelato non essere sicuro e attualmente è consigliato l'algoritmo SHA-2.

Generazione di numeri casuali

La generazione di numeri casuali è fondamentale per molte operazioni di crittografia. Le chiavi di crittografia, ad esempio, devono essere il più casuali possibile in modo che non sia possibile riprodurle. I generatori di numeri casuali di crittografia devono generare output che sia impossibile da prevedere con una probabilità superiore al 50%. Pertanto, qualsiasi metodo di previsione del bit di output successivo non deve avere una prestazione migliore della previsione casuale. Le classi in .NET Framework utilizzano i generatori di numeri casuali per generare chiavi di crittografia.

La classe RNGCryptoServiceProvider è un'implementazione di un algoritmo di generazione di numeri casuali.

Manifesti ClickOnce

In .NET Framework 3.5 sono disponibili le seguenti classi di crittografia che consentono di ottenere e verificare informazioni sulle firme del manifesto per applicazioni distribuite con la tecnologia ClickOnce.

Nelle classi seguenti vengono inoltre fornite informazioni specifiche sulla firma:

Supporto per Suite B

.NET Framework 3.5 supporta l'insieme di algoritmi di crittografia Suite B pubblicati da National Security Agency (NSA). Per ulteriori informazioni su Suite B, vedere NSA Suite B Cryptography Fact Sheet (informazioni in lingua inglese).

Sono inclusi gli algoritmi seguenti:

  • Algoritmo AES (Advanced Encryption Standard) con dimensioni della chiave di 128, 192 e 256 bit per la crittografia.

  • Algoritmi SHA-1, SHA-256, SHA-384 e SHA-512 (Secure Hash Algorithm) per l'hashing. Gli ultimi tre sono in genere raggruppati e noti come SHA-2.

  • Algoritmo ECDSA (Elliptic Curve Digital Signature Algorithm) che utilizza curve di coefficienti di numeri primi di 256, 384 e 521 bit per la generazione della firma. La documentazione NSA definisce in modo specifico queste curve e le chiama P-256, P-384 e P-521. Questo algoritmo viene fornito dalla classe ECDsaCng e consente di firmare con una chiave privata e verificare la firma con una chiave pubblica.

  • Algoritmo ECDH (Elliptic Curve Diffie-Hellman) che utilizza curve di coefficienti di numeri primi di 256, 384 e 521 bit per lo scambio di chiave e la generazione della chiave privata. Questo algoritmo viene fornito dalla classe ECDiffieHellmanCng

Nelle nuove classi AesCryptoServiceProvider, SHA256CryptoServiceProvider, SHA384CryptoServiceProvider e SHA512CryptoServiceProvider sono disponibili wrapper del codice gestito per le implementazioni certificate da FIPS (Federal Information Processing Standard) delle implementazioni AES, SHA-256, SHA-384 e SHA-512.

Classi Cryptography Next Generation (CNG)

Le classi Cryptography Next Generation (CNG) forniscono un wrapper gestito intorno alle funzioni CNG native. CNG sostituisce CryptoAPI. Queste classi contengono "Cng" nel nome. Elemento centrale delle classi wrapper CNG è la classe del contenitore di chiavi CngKey che astrae l'archiviazione e l'utilizzo delle chiavi CNG. Questa classe consente di archiviare in modo sicuro una coppia di chiavi o una chiave pubblica e fare riferimento a tale chiave utilizzando un semplice nome di stringa. La classe di firma basata su curva ellittica ECDsaCng e la classe di crittografia ECDiffieHellmanCng possono utilizzare oggetti CngKey.

La classe CngKey viene utilizzata per una varietà di operazioni aggiuntive, incluse l'apertura, la creazione, l'eliminazione e l'esportazione di chiavi. Fornisce inoltre l'accesso all'handle di chiave sottostante da utilizzare quando le funzioni native vengono chiamate direttamente.

In .NET Framework 3.5 sono inoltre incluse varie classi CNG di supporto, quali le seguenti:

Vedere anche

Concetti

Modello di crittografia di .NET Framework

Esempio di comunicazione protetta tramite Cryptography Next Generation (CNG)

Altre risorse

Attività di crittografia

Servizi di crittografia