Come abbiamo visto nei precedenti post esistono due tipologie di algoritmi di codifica : Simmetrici e Asimmetrici. Vediamo come utilizzarli all'interno del mondo .NET

Chiavi Simmetriche

Cryptography definisce una classe astratta chiamata SymmetricAlgorithm dalla quale tutte le implementazioni di algoritmi simmetrici dovrebbero discendere. Questa classe viene utilizzata per referenziare un oggetto a runtime come mostrato qui di seguito.

SymmetricAlgorithm symAlg = new RijndaelManaged();

.NET 1.1 ha quattro implementazioni di SymmetricAlgorithm.

  1. Data Encryption Standart (DAS)
  2. TripleDES
  3. Rivest Cipher-2 (RC2)
  4. Rijndael (il quale deriva dal nome di Vincent Rijmen e Joan Daeman)

RC2 ha una chiave a lunghezza variabile, DES ha lunghezza di 56-bit mentre TripleDES è fissa di 112bit. L'algoritmo di Rijndael è il nuovo standard a livello governativo USA (si dice che lo chiamino AES), anche se andando a vedere il sito del NSA non sembra essere così. Comunque, l'unica implementazione di tipo Managed di SymmetricAlgorithm è RijndaelManaged, e per questo, è la soluzione maggiormente diffusa e scelta tra le quattro proposte sopra. Iniziamo dunque a dare uno sguardo alle proprietà fino ad arrivare ai metodi proposti da questa classe.

Per prima cosa, SymmetricAlgorithm definisce un set di proprietà che, sinceramente, non ci si aspetterebbe di trovare in una classe di questa "natura". Se per esempio stiamo lavorando con un algoritmo block-based anzichè un algoritmo stream-based, potremmo trovare la lunghezza del base block attraverso BlockSize.

// symAlg = Algoritmo Simmetrico
int blockSize = symAlg.BlockSize;

E' inoltre possibile recuperare e valorizzare (get/set) il vettore d'inizializzazione per gli algoritmi che sono basati sul Cipher Block Chaining (CBC) e riempirlo attraverso la proprietà IV come dimostrato qui di seguito.

byte[] iv = symAlg.IV;

for(int i = 0; i < iv.Length; i++)
{
   iv[i] /= 2;
}

symAlg.IV = iv;

Se si vuole trovare la dimensione della chiave, è necessario chiamare la proprietà KeySize.

byte[] keyMaterial = new byte[symAlg.KeySize];
keyMaterial = symAlg.Key;

Più avanti, vedremo come usare queste proprietà per codificare e decodificare. Per ora, ci basta sapere che possiamo usare queste proprietà per recuperare le informazioni sulla chiave prima di iniziare a codificare informazioni.

Tuttavia, come sappiamo, solo chiavi con una certa lunghezza sono permesse (vengono definite Legali). Inoltre, differenti algoritmi supportano differenti metodi di riempimento (Padding Mode) durante il processo di codifica. Ed è proprio qui che entrara in gioco il successivo set di proprietà. Possiamo usare LegalKeySizes come dimostrato per verificare se la chiave scelta funzionerà o no.

int desiredKeySize = 22;
KeySizes[] legalSize = symAlg.LegalKeySizes;
for(int i = 0; i < legalSize.Length; i++)
{
   
if(desiredKeySize >= legalSize[i].MinSize &&
       desiredKeySize <= legalSize[i].MaxSize &&
       (desiredKeySize % legalSize[i].SkipSize) == 0)
   {
      
// Ok Funziona :-) [Legal Size]
   
}
}

Sinceramente mi sono sempre chiesto perchè SymmetricAlgorithm,m non ha un metodo booleano di nome (mi piace troppo is) IsLegalSize() con lo scopo di confermarci proprio quello che vogliamo, ovvero, se la chiave funzionerà o no. E' comunque possibile creare una classe KeySizesEx che "wrappa" un array KeySizes ed aggiunge questo metodo.

public class KeySizesEx
{
   
private KeySizes[] ks = null;
   
public KeySizesEx(KeySizes[] ks)
   {
      
this.ks = ks;
   }
   
public bool IsValidKeySize(int DesiredSize)
   {
      
bool retVal = false;
      
foreach(KeySizes keySize in ks)
      {
         
if(DesiredSize >= keySize.MinSize &&
                 DesiredSize <= keySize.MaxSize &&
            (DesiredSize % keySize.SkipSize) == 0)
         {
            retVal = 
true;
            
break;
         }
      }
      
return retVal;
   }
}

In questo modo il controllo delle chiavi è molto più semplice da effettuare.

KeySizesEx kse = new KeySizesEx(symAlg.LegalKeySizes);
if(kse.IsValidKeySize(desiredKeySize))
{
   
// Non Funziona [Not Lega]
}
else
{
   
// Funziona [Legal]
}

La proprietà LegalBlockSizes lavora esattamente nello stesso modo in cui lavora LegalKeySizes, quindi andremo ad utilizzare la stessa tecnica per determinare se un block size è "legale" (funzionante) per l'algoritmo scelto.

Esistono una serie di proprietà "enumeration-based" che permettono di specificare la modalità di "riempimento" (Padding Mode). Mode ritorna uno dei 5 valori (CipherMode) enumerator di seguito elencati:

  1. CBC
  2. CFB
  3. CTS
  4. ECB
  5. OFB

Allo stesso modo, Padding ritorna questi valori enumerator che indicano il PaddingMode.

  1. Nome
  2. Public Key Cryptography Standart 7 (PKCS7)
  3. Zeros

A questo punto abbiamo sotto controllo le proprietà di SymmetricAlgorithm. Nel prossimo post scopriremo come usare questa class per codificare dati.