Dopo aver ricevuto ulteriori suggerimenti (come da commenti) ed aver letto in rete articoli inerenti l'argomento, ho nuovamente modificato la classe MD5Helper, in questo modo:
1 public class MD5Helper
2 {
3 System.Security.Cryptography.MD5 _md5 = null;
4
5 public MD5Helper()
6 {
7 _md5 = System.Security.Cryptography.MD5.Create();
8 }
9
10 public byte[] ComputeHash(string text)
11 {
12 return ComputeHash(text, null);
13 }
14
15 private byte[] ComputeHash(string text,byte[] saltBytes)
16 {
17 if (!string.IsNullOrEmpty(text))
18 {
19 if (saltBytes == null) saltBytes = GetSaltBytes();
20 //MD5(text)
21 byte[] textBytes = _md5.ComputeHash(System.Text.UTF8Encoding.UTF8.GetBytes(text));
22 //Crea un unico array di bytes
23 byte[] allBytes = new byte[textBytes.Length+saltBytes.Length];
24
25 Array.Copy(textBytes, 0, allBytes, 0,textBytes.Length);
26 Array.Copy(saltBytes, 0, allBytes, textBytes.Length, saltBytes.Length);
27
28 //MD5((MD5(text)+salt)
29 byte[] hashBytes = _md5.ComputeHash(allBytes);
30 return hashBytes;
31 }
32 else
33 {
34 throw new ArgumentException("Il valore del parametro text non può essere Null o Vuoto");
35 }
36
37 }
38
39 public bool Verify(string text, byte[] hashBytes)
40 {
41 try
42 {
43 byte[] hashSalt = GetSaltBytes();
44 byte[] textHashBytes = ComputeHash(text, hashSalt);
45 string str1 = BitConverter.ToString(textHashBytes);
46 string str2 = BitConverter.ToString(hashBytes);
47 return str1.Equals(str2);
48 }
49 catch
50 {
51 return false;
52 }
53 }
54
55 private byte[] CreateRandomSaltBytes()
56 {
57 byte[] saltBytes = new byte[16];
58 RNGCryptoServiceProvider rng;
59
60 rng = new RNGCryptoServiceProvider();
61 rng.GetBytes(saltBytes);
62
63 return saltBytes;
64 }
65
66 private byte[] GetSaltBytes()
67 {
68 return new byte[] { 13, 100, 12, 15, 13, 55, 33, 55, 44, 33, 84, 67, 190, 254, 89, 99 };
69 }
70
71 public void Close()
72 {
73 _md5.Clear();
74 }
75 }
Ci sono delle piccole osservazioni da fare. Nel caso reale in cui utilizzo questa classe, deve essere "protetta" un unica password (modificabile,senza username, l'applicazione è di tipo Windows Form), per questo ho scelto di utilizzare un salt fisso. Se si dovesse eseguire l'hash di più coppie di username e password, sarebbe necessario creare dei salt random per ogni coppia (usando ad esempio la funzione CreateRandomSaltBytes), memorizzando l'opportuno salt in un database, e utilizzandolo per l'autenticazione degli utenti. Una lettura a riguardo, tratta da MSDN Magazine, la si può trovare al seguente indirizzo: http://msdn2.microsoft.com/it-it/magazine/cc164107(en-us).aspx. Da quanto appreso in altre letture su internet, RSA Security considera l'MD5 poco sicuro ( correggetemi se sbaglio!), consigliando di utilizzare invece algoritmi di hashing del tipo SHA1, SHA256, SHA384 etc....