Per codificare\decodificare informazioni, vengono utilizzati i metodi CreateEncryptor() o CreateDecryptor() della classe SymmetricAlgorithm. Esistono due versioni di questi metodi: uno senza alcun tipo di parametro richiesto (parameterless) ed un secondo che richiede due byte di array, i quali, rappresentano il IV e la chiave per il processo di codifica. In entrambe i casi, il valore di ritorno è una interfaccia ICryptoTransform. Al netto di ciò, come segue, possiamo usare direttamente CryptoStream per rendere il nostro lavoro più facile.
1 String adPath = AppDomain.CurrentDomain.SetupInformation.ApplicationBase;
2 FileStream fin = new FileStream(adPath + @"\jcfileIN.txt",
3 FileMode.Open, FileAccess.Read);
4 MemoryStream mout = new MemoryStream();
5 byte[] finData = new byte[fin.Length];
6
7 SymmetricAlgorithm rijn = Rijndael.Create();
8 CryptoStream coutenc = new CryptoStream(mout, rijn.CreateEncryptor(),
9 CryptoStreamMode.Write);
10 fin.Read(finData, 0, (int)fin.Length);
11 coutenc.Write(finData, 0, (int)fin.Length);
12 coutenc.FlushFinalBlock();
13
14 FileStream fdec = new FileStream(adPath + @"\jcfileOUT.txt",
15 FileMode.OpenOrCreate, FileAccess.Write);
16
17 CryptoStream coutdec = new CryptoStream(fdec, rijn.CreateDecryptor(),
18 CryptoStreamMode.Write);
19 coutdec.Write(mout.GetBuffer(), 0, (int)(mout.Length));
20 coutdec.Close();
21
Ok parliamoci chiaro, questo codice può sembrare molto simile a quello postato in uno dei precedenti post, tuttavia c'è un particolare che dovrebbe essere analizzato per bene. Dopo che tutte le informazioni del file sono state scritte, e quindi codificate, non ho chiamato Close(); ma ho chiamato FlushFinalBlock(). A dirla tutta esistono due buoni motivi che hanno motivato questa scelta. La prima è che ho bisogno dell'interno buffer archiviato per decodificare i dati. Se avessi chiamato il metodo Close(); avrei perso l'intero stream di memoria e quindi.. non avrei potuto decodificarli.
La seconda motivazione non è tanto apparente quanto possa sembrare. Ricordiamoci che gli algoritmi di codifica possono essere blockdor stream-based. Rijanadel è un algoritmo block based (di fatto l'intero blocco è di 128bit), quindi usa il padding (PKCS7 di default) per assicurarsi la dimensione corretta del blocco. Quando decodifichiamo il buffer dello stream di memoria, dobbiamo essere sicuri che, la decodifica abbia "extra" padding in modo da avere il file di risultato di eguali dimensioni dell'originale. Quando si chiama il metodo FlushFinalBlock(), la dimensione dello stream di memoria sarà uguale alla lunghezza del buffer originale più la dimensione del padding. Facendo due rapidi calcoli il buffer di memoria sarà più o meno il doppio della lunghezza dell'originario; quindi non preoccupatevi riguardo la lunghezza del buffer quando chiamate Length.