Prima d'iniziare è necessario dare uno sguardo veloce allo spazio di nomi System.Security.Cryptography, che da questo punto in poi sarà il nostro punto di rifermento al concetto di Cryptografia.
Come la maggior parte degli spazi di nomi di .NET, ci sono molti membri che necessitano di uno occhiata approfondita, Per esempio questo spazio di nomi ha le sue classi stream (CryptoStream), classi hash astratte (HashAlgorithm), algoritmi simmetrici (RijndaelManaged) ed altro. Queste classi sono state create per rendere facile al programmatore per riferirsi ad un oggetto a runtime con una considerevole flessibilità. Come si può vedere questo design permette di utilizzare contemporaneamente differenti implementazioni criptografiche. E' inoltre possibile aggiungere nuove implementazioni, sia personali che di terze parti.
.NET Cryptographic Exceptions
Non tutto può andar sempre bene, anche i software migliori possono presentare errori. E' quindi bene sapere che .NET definisce due classi di eccezione per la Cryptografia.
CryptographicException
CryptographicUnexpectedOperationException (!!)
Capire le classi Hash-Based
Come abbiamo detto HashAlgorithm è una classe astratta che definisce metodi che tutti gli algortimi di hash possono implementare. Inoltre, eredita dall'interfaccia ICryptoTransform. .NET ha un numero di classi astratte che estendono la classe astratta HashAlgorithm, come, per esempio, KeyedHashAlgorithm, MD5 (Message Digest 5) e SHA1 (Secure Hash Algorithm-1). La principale differenza tra SHA1 e MD5 è la dimensione del hash. MD5 produce un valore di hash di lunghezza 128 bits, mentre SHA1 può produrre valori di hash maggiori (160bits o maggiori), il quale di fatto lo rende più resistente ad attacchi di brute force (attacchi brutali). E' bene sapere che esistono quattro (4) differenti versioni di classi astratte basate su SHA. SHA1,SHA256,SHA384,SHA512. 256,384,512 definiscono la lunghezza in bit del valore di hash. SHA1 produrrà sempre un valore di hash di lunghezza a 160bits.
Implementazioni basate su KeyedHashAlgorithm funzionano come gli altri algoritmi di hash ad eccezione del fatto che queste usano una chiave durante il processo di hashing. Queste classi astratte hanno classi corrispondenti. Aprendo una piccola parentesi, andiamo ad analizzare queste classi derivate.
Per esempio, osservando SHA1, verrete avvisati che .NET definisce due sottoclassi. SHA1CryptoServiceProvider e SHA1Managed (le altre versioni di SHA hanno solo classi Managed). La stessa nomenclatura verrà verificata anche per le altre classi derivate. Quale è quindi la differenza tra queste? La risposta è nella convenzione con cui sono state definite. Se una classe contiene il suffisso "CryptoServiceProvider" (di seguito CSP) significa che questa sta utilizzando il crypto service provider di Windows. Le classi "Managed" invece eseguono tutte le operazioni a loro assegnate per loro conto (senza far alcun riferimento al sistema operativo). In poche parole tutte le classi con suffisso CSP utilizzeranno chiamate P/Invoke unmanaged a CryptoAPI per eseguire le operazioni richieste. Mentre le "Managed" utilizzerano gli strumenti interni del .NET Framework.
Oltre alla classe KeyedHashAlgorithm (la quale espone la proprietà Key), nessuno delle sotto classi HashAlgorithm espongono nuovi metodi a HashAlgorithm. Di conseguenza, è raccomandabile "bindare" queste interfacce ad una classe concreta al momento di construction. Di seguito un esempio.
1 HashAlgorithm hash = new SHA1Managed();
Tuttavia, tutte le sottoclassi di HashAlgorithm eseguono un overload del metodo Create(), che può essere utilizzato per creare una classe che implementa uno specifico algoritmo di hash. Eccone un esempio
1 try
2 {
3 hash = SHA1.Create("SHA");
4 }
5 catch (CryptographicUnexpectedOperationException ce)
6 {}
E' raccomandabile utilizzare sempre la prima tecnica. La seconda tecnica è utilie se si ha bisogno di eseguire un numero di operazioni di hashing che andranno ad utilizzare differenti implementazioni. Questo perchè la caratteristica più apprezzabile derivata dall'utilizzo di .Create() è proprio quella di ritornare la corretta istanza.
Come abbiamo visto .Create() può sollevare una eccezione di tipo CryptographicUnexpectedOperationException se l'argomento "Name" risultasse incorretto. E' possibile anche chiamare il metodo .Create() senza specificare l'argomento "Name", il quale, di default, creerà un oggetto di tipo HashAlgorithm Based.
A questo punto "la domanda sorge spontanea". Come può .NET determinare se un valore dell'argomento "Name" è corretto o no? La risposta si può trovare in due punti.
- CryptoConfig
- machine.config
La risposta e la descrizione di questi oggetti nel prossimo post ;).