seguridad encriptar encriptado desencriptar datos archivos aplicaciones c# .net encryption aes

c# - encriptar - Encriptación AES en archivos grandes



encriptar cookies c# (3)

Como está leyendo un archivo y escribiendo en un archivo, simplemente reemplace las secuencias de memoria por IOStream o FileStream.

Tendrá que refactorizar los procedimientos un poco para que no esperen / devuelvan matrices de bytes.

Necesito cifrar y descifrar un archivo grande (~ 1GB). Intenté usar este ejemplo: http://www.codeproject.com/Articles/769741/Csharp-AES-bits-Encryption-Library-with-Salt Pero mi problema es que el archivo es muy grande, me sale la excepción de OutOfMemory . Así que necesito reemplazar la secuencia de la memoria con la secuencia de archivos, simplemente no estoy seguro de cómo hacerlo ...

(Agregando mi código :)

private static void AES_Encrypt(string srcFile, string encryptedFile, byte[] passwordBytes) { // Set your salt here, change it to meet your flavor: // The salt bytes must be at least 8 bytes. byte[] saltBytes = new byte[] { 1, 2, 3, 4, 5, 6, 7, 8}; FileStream fsInput = new FileStream(srcFile, FileMode.Open, FileAccess.Read); FileStream fsEncrypted = new FileStream(encryptedFile, FileMode.Create, FileAccess.Write); using (RijndaelManaged AES = new RijndaelManaged()) { AES.KeySize = 256; AES.BlockSize = 128; var key = new Rfc2898DeriveBytes(passwordBytes, saltBytes, 1000); AES.Key = key.GetBytes(AES.KeySize / 8); AES.IV = key.GetBytes(AES.BlockSize / 8); AES.Mode = CipherMode.CBC; using (var cs = new CryptoStream(fsEncrypted, AES.CreateEncryptor(), CryptoStreamMode.Write)) { byte[] bytearrayinput = new byte[fsInput.Length - 1]; fsInput.Read(bytearrayinput, 0, bytearrayinput.Length); cs.Write(bytearrayinput, 0, bytearrayinput.Length); cs.Close(); fsInput.Flush(); fsInput.Close(); fsEncrypted.Close(); } } } public static void AES_Decrypt(string encryptedFile, string decryptedFile, byte[] passwordBytes) { byte[] decryptedBytes = null; // Set your salt here, change it to meet your flavor: // The salt bytes must be at least 8 bytes. byte[] saltBytes = new byte[] { 1, 2, 3, 4, 5, 6, 7, 8}; FileStream fsread = new FileStream(encryptedFile, FileMode.Open, FileAccess.Read); using (RijndaelManaged AES = new RijndaelManaged()) { AES.KeySize = 256; AES.BlockSize = 128; var key = new Rfc2898DeriveBytes(passwordBytes, saltBytes, 1000); AES.Key = key.GetBytes(AES.KeySize / 8); AES.IV = key.GetBytes(AES.BlockSize / 8); AES.Mode = CipherMode.CBC; FileStream fsDecrypted = new FileStream(decryptedFile, FileMode.Create, FileAccess.Write); using (var cs = new CryptoStream(fsDecrypted, AES.CreateDecryptor(), CryptoStreamMode.Write)) { byte[] bytearrayinput = new byte[fsread.Length - 1]; fsread.Read(bytearrayinput, 0, bytearrayinput.Length); cs.Write(bytearrayinput, 0, bytearrayinput.Length); cs.Close(); fsread.Close(); fsDecrypted.Close(); } } }


Eventualmente, este es el código que funcionó para mí:

private static void AES_Encrypt(string inputFile, string outputFile, byte[] passwordBytes) { byte[] saltBytes = new byte[] { 1, 2, 3, 4, 5, 6, 7, 8}; string cryptFile = outputFile; FileStream fsCrypt = new FileStream(cryptFile, FileMode.Create); RijndaelManaged AES = new RijndaelManaged(); AES.KeySize = 256; AES.BlockSize = 128; var key = new Rfc2898DeriveBytes(passwordBytes, saltBytes, 1000); AES.Key = key.GetBytes(AES.KeySize / 8); AES.IV = key.GetBytes(AES.BlockSize / 8); AES.Padding = PaddingMode.Zeros; AES.Mode = CipherMode.CBC; CryptoStream cs = new CryptoStream(fsCrypt, AES.CreateEncryptor(), CryptoStreamMode.Write); FileStream fsIn = new FileStream(inputFile, FileMode.Open); int data; while ((data = fsIn.ReadByte()) != -1) cs.WriteByte((byte)data); fsIn.Close(); cs.Close(); fsCrypt.Close(); } private static void AES_Decrypt(string inputFile, string outputFile, byte[] passwordBytes) { byte[] saltBytes = new byte[] { 1, 2, 3, 4, 5, 6, 7, 8}; FileStream fsCrypt = new FileStream(inputFile, FileMode.Open); RijndaelManaged AES = new RijndaelManaged(); AES.KeySize = 256; AES.BlockSize = 128; var key = new Rfc2898DeriveBytes(passwordBytes, saltBytes, 1000); AES.Key = key.GetBytes(AES.KeySize / 8); AES.IV = key.GetBytes(AES.BlockSize / 8); AES.Padding = PaddingMode.Zeros; AES.Mode = CipherMode.CBC; CryptoStream cs = new CryptoStream(fsCrypt, AES.CreateDecryptor(), CryptoStreamMode.Read); FileStream fsOut = new FileStream(outputFile, FileMode.Create); int data; while ((data = cs.ReadByte()) != -1) fsOut.WriteByte((byte)data); fsOut.Close(); cs.Close(); fsCrypt.Close(); } }


Así que creé una versión bastante rápida y de bajo consumo de memoria:
Utilizo un "buffer temporal" y también "uso una sal aleatoria y lo almaceno con el texto cifrado".
Para encriptar:

private void AES_Encrypt(string inputFile, string password) { //http://.com/questions/27645527/aes-encryption-on-large-files //generate random salt byte[] salt = GenerateRandomSalt(); //create output file name FileStream fsCrypt = new FileStream(inputFile + ".aes", FileMode.Create); //convert password string to byte arrray byte[] passwordBytes = System.Text.Encoding.UTF8.GetBytes(password); //Set Rijndael symmetric encryption algorithm RijndaelManaged AES = new RijndaelManaged(); AES.KeySize = 256; AES.BlockSize = 128; AES.Padding = PaddingMode.PKCS7; //http://.com/questions/2659214/why-do-i-need-to-use-the-rfc2898derivebytes-class-in-net-instead-of-directly //"What it does is repeatedly hash the user password along with the salt." High iteration counts. var key = new Rfc2898DeriveBytes(passwordBytes, salt, 50000); AES.Key = key.GetBytes(AES.KeySize / 8); AES.IV = key.GetBytes(AES.BlockSize / 8); //Cipher modes: http://security.stackexchange.com/questions/52665/which-is-the-best-cipher-mode-and-padding-mode-for-aes-encryption AES.Mode = CipherMode.CFB; //write salt to the begining of the output file, so in this case can be random every time fsCrypt.Write(salt, 0, salt.Length); CryptoStream cs = new CryptoStream(fsCrypt, AES.CreateEncryptor(), CryptoStreamMode.Write); FileStream fsIn = new FileStream(inputFile, FileMode.Open); //create a buffer (1mb) so only this amount will allocate in the memory and not the whole file byte[] buffer = new byte[1048576]; int read; try { while ((read = fsIn.Read(buffer, 0, buffer.Length)) > 0) { Application.DoEvents(); // -> for responsive GUI, using Task will be better! cs.Write(buffer, 0, read); } //close up fsIn.Close(); } catch (Exception ex) { Debug.WriteLine("Error: " + ex.Message); } finally { cs.Close(); fsCrypt.Close(); } }

Para descifrar:

private void AES_Decrypt(string inputFile, string password) { //todo: // - create error message on wrong password // - on cancel: close and delete file // - on wrong password: close and delete file! // - create a better filen name // - could be check md5 hash on the files but it make this slow byte[] passwordBytes = System.Text.Encoding.UTF8.GetBytes(password); byte[] salt = new byte[32]; FileStream fsCrypt = new FileStream(inputFile, FileMode.Open); fsCrypt.Read(salt, 0, salt.Length); RijndaelManaged AES = new RijndaelManaged(); AES.KeySize = 256; AES.BlockSize = 128; var key = new Rfc2898DeriveBytes(passwordBytes, salt, 50000); AES.Key = key.GetBytes(AES.KeySize / 8); AES.IV = key.GetBytes(AES.BlockSize / 8); AES.Padding = PaddingMode.PKCS7; AES.Mode = CipherMode.CFB; CryptoStream cs = new CryptoStream(fsCrypt, AES.CreateDecryptor(), CryptoStreamMode.Read); FileStream fsOut = new FileStream(inputFile + ".decrypted", FileMode.Create); int read; byte[] buffer = new byte[1048576]; try { while ((read = cs.Read(buffer, 0, buffer.Length)) > 0) { Application.DoEvents(); fsOut.Write(buffer, 0, read); } } catch (System.Security.Cryptography.CryptographicException ex_CryptographicException) { Debug.WriteLine("CryptographicException error: " + ex_CryptographicException.Message); } catch (Exception ex) { Debug.WriteLine("Error: " + ex.Message); } try { cs.Close(); } catch (Exception ex) { Debug.WriteLine("Error by closing CryptoStream: " + ex.Message); } finally { fsOut.Close(); fsCrypt.Close(); } }

Para generar sal aleatoria:

public static byte[] GenerateRandomSalt() { //Source: http://www.dotnetperls.com/rngcryptoserviceprovider byte[] data = new byte[32]; using (RNGCryptoServiceProvider rng = new RNGCryptoServiceProvider()) { // Ten iterations. for (int i = 0; i < 10; i++) { // Fill buffer. rng.GetBytes(data); } } return data; }