Guida al Visual Basic .NET
Capitolo 102° - Sicurezza e criptazione
Anche in questo ambito, il Framework offre ottime funzionalità, procurando al programmatore molti modi per cifrare e decifrare messaggi che non dovebbero essere intercettabili da alcun altra persona che non sia l'utente. Le classi che servono per questo scopo sono esposte nei namespace System.Security e System.Security.Cryptography. Dopo una breve introduzione, mostrerò come sia possibile criptare e decriptare dati usando queste potenzialità. Introduzione alla criptazioneLa criptazione è una disciplina informatica che si occupa di oscurare messaggi o dati in modo da renderli accessibili solo alle persone alle quali sono realemnte destinati. Così facendo, si evita che qualche cracker indesiderato possa impossessarsene ed utilizzare le informazioni ivi contenute per chissà quali scopi. Esistono tre tipi di algoritmi di criptazione:
Il .Net Framework mette a disposizione wrapper per i seguenti algoritmi:
Una prova pratica
Nei seguenti esempi, fornirò una dimostrazione del funzionamento degli algoritmi simmetrici e di hashing. Poiché i primi
derivando tutti dalla classe base SymmetricAlgorithm e i secondi da HashAlgorithm, il funzionamento illustrato per uno solo di questi può
essere ripetuto in maniera identica (eccetto che per dimensione della chiave) per ogni altro algoritmo della stessa famiglia. Imports System.Security Imports System.Security.Cryptography Imports System.Text.UTF8Encoding Module Module1 'Vettore di bytes casuali usati per oscurare la chiave: 'verrà usato nella funzione di derivazione della password Private SaltBytes As Byte() = New Byte() _ {162, 21, 92, 34, 27, 239, 64, 30, 136, 102, 223} 'Questo è un vettore di inizializzazione per algoritmi 'simmetrici a 256-bit. Si nota, infatti, che è lungo 32 bytes Private IV32 As Byte() = New Byte() _ {133, 206, 56, 64, 110, 158, 132, 22, _ 99, 190, 35, 129, 101, 49, 204, 248, _ 251, 243, 13, 194, 160, 195, 89, 152, _ 149, 227, 245, 5, 218, 86, 161, 124} 'La derivazione di password è un'altra delle tecniche 'usate in criptazione: si cifra la chiave iniziale con un 'algoritmo di derivazione, fornendo come base un vettore 'di bytes casuali, chiamato salt crittografico. 'L'algoritmo applica una trasformazione sulla chiave un 'numero dato di volte (iterazioni) e restituisce alla fine una 'password di lunghezza specificata. In questo caso, poiché 'si sta utilizzando l'algoritmo Rijndael a 256 bit, sarà 'di 32 bytes Private Function DerivePassword(ByVal Key As String) As Byte() 'Il provider crittografico Dim Derive As Rfc2898DeriveBytes 'Il risultato dell'operazione Dim DerivedBytes() As Byte 'Crea un nuovo provider crittografico per l'algoritmo 'di derivazione RFC2898, che ha come input Key, come 'salt crittografico l'array SaltBytes sopra definito 'e come numero di iterazioni 5. Il secondo e il terzo 'parametro sono del tutto casuali: li si può 'modificare arbitrariamente Derive = New Rfc2898DeriveBytes(Key, SaltBytes, 5) 'Applica la trasformazione e deriva una nuova password 'ottenuta come array di 32 bytes DerivedBytes = Derive.GetBytes(32) Return DerivedBytes End Function 'Data una chiave Key e un messaggio Text, usa l'algoritmo simmetrico 'a blocchi Rijndael (AES) per ottenere un insieme di dati criptato Public Function RijndaelEncrypt(ByVal Key As String, _ ByVal Text As String) As Byte() 'Crea il nuovo provider crittografico per questo algoritmo Dim Provider As New RijndaelManaged 'La password derivata Dim BytePassword As Byte() 'L'oggetto che ha il compito di processare le informazioni Dim Encryptor As ICryptoTransform 'L'output della funzione Dim Output As Byte() 'L'input della funzione, ossia il testo convertito 'in forma binaria. Il formato UTF8 permette di 'mantenere anche i caratteri speciali come quelli accentati Dim Input As Byte() = UTF8.GetBytes(Text) 'Imposta la dimensione della chiave Provider.KeySize = 256 'Imposta la dimensione del blocco Provider.BlockSize = 256 'Ottiene la password tramite derivazione dalla chiave BytePassword = DerivePassword(Key) 'Crea un nuovo oggetto codificatore Encryptor = Provider.CreateEncryptor(BytePassword, IV32) 'Cripta il testo Output = Encryptor.TransformFinalBlock(Input, 0, Input.Length) 'Elimina le informazioni fornite al provider Provider.Clear() 'Distrugge l'oggetto codificatore Encryptor.Dispose() Return Output End Function 'Data una chiave Key e un messaggio cifrato Data, usa l'algoritmo 'simmetrico a blocchi Rijndael (AES) per ottenere l'insieme di 'dati di partenza Public Function RijndaelDecrypt(ByVal Key As String, _ ByVal Data() As Byte) As String 'Crea un nuovo provider crittografico Dim Provider As New RijndaelManaged 'La password derivata Dim BytePassword As Byte() 'L'oggetto che ha il compito di processare le informazioni Dim Decryptor As ICryptoTransform 'L'output della funzione in bytes Dim Output As Byte() Provider.KeySize = 256 Provider.BlockSize = 256 BytePassword = DerivePassword(Key) 'Ottiene l'oggetto decodificatore Decryptor = Provider.CreateDecryptor(BytePassword, IV32) 'Tenta di decriptare il messaggio: se la chiave è 'sbagliata, lancia un'eccezione Try Output = Decryptor.TransformFinalBlock(Data, 0, Data.Length) Catch Ex As Exception Throw New CryptographicException("Criptazione fallita!") Finally Provider.Clear() Decryptor.Dispose() End Try Return UTF8.GetString(Output) End Function 'I dati prodotti in output sono allocati in vettori di bytes, 'ma le stringhe non sono il supporto più adatto per 'visualizzarli, poiché vengono compresi anche 'caratteri di controllo o null terminator. In ogni caso, 'la stringa sarebbe o compromessa o illeggibile (non che 'non lo debba essere). Questa funzione restituisce tutto 'il vettore come rappresentazione esadecimale in stringa 'rendendo più gradevole la vista del nostro 'magnifico messaggio cifrato Public Function ToHex(ByVal Bytes() As Byte) As String Dim Result As New StringBuilder For I As Int32 = 0 To Bytes.Length - 1 'Accoda alla stringa il codice in formato esadecimale, 'facendo in modo che occupi sempre due posti, eventualmente 'pareggiando con uno zero sulla sinistra Result.AppendFormat("{0:X2}", Bytes(I)) Next Return Result.ToString End Function Sub Main() Dim Input, Output As String Dim Key As String Console.WriteLine("Inserire un testo qualsiasi:") Input = Console.ReadLine Console.WriteLine("Inserire una chiave di criptazione:") Key = Console.ReadLine Try Output = ToHex(RijndaelEncrypt(Key, Input)) Console.WriteLine() Console.WriteLine("Il testo criptato è:") Console.WriteLine(Output) Catch CE As CryptographicException Console.WriteLine("Password errata!") End Try Console.ReadKey() End Sub End Module E questo per l'Hash: Imports System.Security Imports System.Security.Cryptography Imports System.Text.UTF8Encoding Module Module2 'Questa semplice funzione genera un hash MD5 Public Function GetMd5(ByVal Text As String) As Byte() Dim Input As Byte() = UTF8.GetBytes(Text) Dim Output As Byte() 'MD5.Create() crea un nuovo provider crittografico per l'hash Md5 Output = MD5.Create().ComputeHash(Input, 0, Input.Length) Return Output End Function Sub Main() Dim Input As String Console.WriteLine("Inserire un testo qualsiasi:") Input = Console.ReadLine Console.WriteLine() Console.WriteLine("Il suo hash è:") Console.WriteLine(ToHex(GetMd5(Input))) Console.ReadKey() End Sub End Module
C#, TypeScript, java, php, EcmaScript (JavaScript), Spring, Hibernate, React, SASS/LESS, jade, python, scikit, node.js, redux, postgres, keras, kubernetes, docker, hexo, etc...
|