Vai all'aggiornamento di seguito < Non sai come creare un collegamento: (
Ho apportato alcune migliorie al codice da: Csharp- AES-bits-crittografia-Biblioteca-con-Salt
- saltBytes ora è SHA512 della password.
- Casuale IV per ogni chiamata di crittografia. (IV lunghezza 16 viene aggiunta al file crittografato, rimossa dal file prima della decrittografia)
Vedi qualche difetto, qualcosa che ha bisogno di ottimizzazione? In particolare, le mie domande sono:
-
Il mio metodo
generateIV()
di seguito nel "Codice di crittografia" è sicuro e protetto? Si noti che la sua unica dipendenza è su .NETRNGCryptoServiceProvider Class
. -
È sicuro usare l'hash della password come un salino? o dovrebbe essere casuale come la IV e archiviata insieme al testo cifrato?
Solo per riferimento, ecco il mio codice.
Il codice qui sotto funziona, ho eseguito un test per crittografare due file di testo con lo stesso testo all'interno di ciascuno. Il risultato è che entrambi hanno dati diversi e decrittano.
Inoltre, ho controllato prima del IV casuale, entrambi i file avevano lo stesso testo crittografato, risultati negli stessi dati.
Codice di crittografia:
private static int IV_LENGTH = 16;
public static byte[] AES_Encrypt(byte[] bytesToBeEncrypted, byte[] passwordBytes)
{
byte[] encryptedBytes = null;
byte[] encryptedBytesAndIV = null;
byte[] saltBytes = SHA512.Create().ComputeHash(passwordBytes);
using (System.IO.MemoryStream ms = new System.IO.MemoryStream())
{
using (AesCryptoServiceProvider AES = new AesCryptoServiceProvider())
{
AES.KeySize = 256;
//AES.BlockSize = 128;
var key = new Rfc2898DeriveBytes(passwordBytes, saltBytes, 100);
AES.Key = key.GetBytes(AES.KeySize / 8);
AES.IV = generateIV();
AES.Mode = CipherMode.CBC;
using (var cs = new CryptoStream(ms, AES.CreateEncryptor(), CryptoStreamMode.Write))
{
cs.Write(bytesToBeEncrypted, 0, bytesToBeEncrypted.Length);
cs.Close();
}
encryptedBytes = ms.ToArray();
encryptedBytesAndIV = new byte[encryptedBytes.Length + AES.IV.Length];
AES.IV.CopyTo(encryptedBytesAndIV, 0);
encryptedBytes.CopyTo(encryptedBytesAndIV, IV_LENGTH);
}
}
return encryptedBytesAndIV;
}
private static byte[] generateIV()
{
using (RNGCryptoServiceProvider rng = new RNGCryptoServiceProvider())
{
byte[] nonce = new byte[IV_LENGTH];
rng.GetBytes(nonce);
return nonce;
}
}
Codice di decrittazione:
public static byte[] AES_Decrypt(byte[] bytesToBeDecrypted, byte[] passwordBytes)
{
byte[] decryptedBytes = null;
byte[] saltBytes = SHA512.Create().ComputeHash(passwordBytes);
using (MemoryStream ms = new MemoryStream())
{
using (AesCryptoServiceProvider AES = new AesCryptoServiceProvider())
{
AES.KeySize = 256;
//AES.BlockSize = 128;
var key = new Rfc2898DeriveBytes(passwordBytes, saltBytes, 100);
AES.Key = key.GetBytes(AES.KeySize / 8);
AES.IV = getIV(bytesToBeDecrypted);
bytesToBeDecrypted = removeTagAndIV(bytesToBeDecrypted);
AES.Mode = CipherMode.CBC;
using (var cs = new CryptoStream(ms, AES.CreateDecryptor(), CryptoStreamMode.Write))
{
cs.Write(bytesToBeDecrypted, 0, bytesToBeDecrypted.Length);
cs.Close();
}
decryptedBytes = ms.ToArray();
}
}
return decryptedBytes;
}
private static byte[] removeTagAndIV(byte[] arr)
{
byte[] enc = new byte[arr.Length - IV_LENGTH];
Array.Copy(arr, IV_LENGTH, enc, 0, arr.Length - IV_LENGTH);
return enc;
}
private static byte[] getIV(byte[] arr)
{
byte[] IV = new byte[IV_LENGTH];
Array.Copy(arr, 0, IV, 0, IV_LENGTH);
return IV;
}
Aggiornamento:
Ecco un codice aggiornato basato su commenti / raccomandazioni / consigli
- Random Salt True
- iterazioni 100000
Crittografia:
public static byte[] AES_Encrypt(byte[] bytesToBeEncrypted, byte[] passwordBytes)
{
byte[] encryptedBytes = null;
byte[] encryptedBytesFinal = null;
byte[] saltBytes = generateIVandSalt(16);
using (System.IO.MemoryStream ms = new System.IO.MemoryStream())
{
using (AesCryptoServiceProvider AES = new AesCryptoServiceProvider())
{
AES.KeySize = 256;
var key = new Rfc2898DeriveBytes(passwordBytes, saltBytes, 100000);
AES.Key = key.GetBytes(AES.KeySize / 8);
AES.IV = generateIVandSalt(16);
AES.Mode = CipherMode.CBC;
using (var cs = new CryptoStream(ms, AES.CreateEncryptor(), CryptoStreamMode.Write))
{
cs.Write(bytesToBeEncrypted, 0, bytesToBeEncrypted.Length);
cs.Close();
}
encryptedBytes = ms.ToArray();
encryptedBytesFinal = new byte[encryptedBytes.Length + AES.IV.Length + saltBytes.Length];
AES.IV.CopyTo(encryptedBytesFinal, 0);
saltBytes.CopyTo(encryptedBytesFinal, 16);
encryptedBytes.CopyTo(encryptedBytesFinal, 16 + 16);
}
}
return encryptedBytesFinal;
}
private static byte[] generateIVandSalt(int len)
{
using (RNGCryptoServiceProvider rng = new RNGCryptoServiceProvider())
{
byte[] nonce = new byte[len];
rng.GetBytes(nonce);
return nonce;
}
}
Decodifica:
public static byte[] AES_Decrypt(byte[] bytesToBeDecrypted, byte[] passwordBytes)
{
byte[] decryptedBytes = null;
byte[] saltBytes = getSalt(bytesToBeDecrypted);
using (MemoryStream ms = new MemoryStream())
{
using (AesCryptoServiceProvider AES = new AesCryptoServiceProvider())
{
AES.KeySize = 256;
var key = new Rfc2898DeriveBytes(passwordBytes, saltBytes, 100000);
AES.Key = key.GetBytes(AES.KeySize / 8);
AES.IV = getIV(bytesToBeDecrypted);
bytesToBeDecrypted = removeIVandSalt(bytesToBeDecrypted);
AES.Mode = CipherMode.CBC;
using (var cs = new CryptoStream(ms, AES.CreateDecryptor(), CryptoStreamMode.Write))
{
cs.Write(bytesToBeDecrypted, 0, bytesToBeDecrypted.Length);
cs.Close();
}
decryptedBytes = ms.ToArray();
}
}
return decryptedBytes;
}
private static byte[] removeIVandSalt(byte[] arr)
{
byte[] enc = new byte[arr.Length - 16 - IV_LENGTH];
Array.Copy(arr, IV_LENGTH + 16, enc, 0, arr.Length - IV_LENGTH - 16);
return enc;
}
private static byte[] getIV(byte[] arr)
{
byte[] IV = new byte[IV_LENGTH];
Array.Copy(arr, 0, IV, 0, IV_LENGTH);
return IV;
}
private static byte[] getSalt(byte[] arr)
{
byte[] salt = new byte[16];
Array.Copy(arr, IV_LENGTH, salt, 0, 16);
return salt;
}