Ha szimmetrikus kulcsú titkosítást (Rijndael, AES) akarsz használni, nem mindegy, hogyan.
A .NET framework ugyanis önmagában jól működik, de ha más rendszerekkel kompatibilis kódot szeretnénk készíteni, akkor oda kell figyelni.
Alapesetben a titkosításhoz elő kell állítani egy kulcsot (Key) és egy inicializáló vektort (IV).
Ehhez az alábbi kódot lehet használni:
byte[] salt = new byte[]{ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };
PasswordDeriveBytes pdb = new PasswordDeriveBytes( “mypassword”, salt );
byte[] key = pdb.GetBytes( 16 );
byte[] iv = pdb.GetBytes( 8 );
Ez jó lenne, de mivel a Microsoft nem igazán dokumentálta a PasswordDeriveBytes osztály működését, Mono – azaz Linux alatt csak egy hasonló eljárást tudtak létrehozni, ami viszont nem kompatibilis a MS féle megvalósítással. Ha olyan kódot írunk, aminél szükség van az átjárhatóságra (például Windows szerver, Linux kliens), akkor ez nem fog működni, mert a két platformon teljesen más értékeket fogunk visszakapni.
Mit lehet tenni? Szerencsére van egy alternatív megoldás, az Rfc2898DeriveBytes osztály, ami viszont mindkét platformon ugyanúgy működik.
Rfc2898DeriveBytes rdb = new Rfc2898DeriveBytes( “mypassword”, salt );
A kettő közt a fő különbség az, hogy a PasswordDeriveBytes a PBKDF1 algoritmust használja a byte tömbök előállítására, míg az Rfc2898DeriveBytes ennek a következő verzióját, a PBKDF2-t, és ez kellően dokumentált.
De mire ezt kideríti az ember!
Frissítés!
Arra viszont figyelni kell, hogy az Rfc2898DeriveBytes kódolási időigénye kb 25x nagyobb, mint a PasswordDeriveBytes algoritmusé egy 14 karakteres jelszó és egy 20 byte-os salt esetén. Ez azt jelenti, hogy a hash-elt Key és IV tömböket érdemes a memóriában tárolni a futási idő alatt, mert jelentős időveszteséget jelenthet egy ciklikus feldolgozás esetén.