首页 > 解决方案 > 如何使用 AES256 算法从多页文件中提取单个解密页面

问题描述

我创建了一个 Winform 测试应用程序,用于检查AES256加密/解密是否适用于大文件。

我有一个包含多个页面的单个文本文件,它的大小为 7.32GB,总页数为 180 万。

我正在尝试使用 AES256 算法加密和解密这个多页文本文件。

目前加密需要 3 分钟,解密需要将近 3 分钟。但我有以下担忧,

所以如果我们想从该文档中提取单个页面,我们是否需要完全解密它?或者有什么方法可以让我们访问文件的各个部分而不会产生开销?

我使用了以下代码:

加密:

public static void Encrypt(string password, string inputFile, string outputFile)
{
    //http://stackoverflow.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 AES symmetric encryption algorithm
    AesManaged AES = new AesManaged();
    AES.KeySize = 256;
    AES.BlockSize = 128;
    AES.Padding = PaddingMode.PKCS7;

    //http://stackoverflow.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.ECB;

    // 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)
    {
        Console.WriteLine("Error: " + ex.Message);
    }
    finally
    {
        cs.Close();
        fsCrypt.Close();
    }
    //using (FileStream infs = File.OpenRead(inputfile))
    //using (FileStream outfs = File.Create(outputfile))
    //    Encrypt(password, infs, outfs);
}

解密:

public static void Decrypt(string password, string inputFile, string outputFile)
{
    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);

    AesManaged AES = new AesManaged();
    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.ECB;

    CryptoStream cs = new CryptoStream(fsCrypt, AES.CreateDecryptor(), CryptoStreamMode.Read);

    FileStream fsOut = new FileStream(outputFile, 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 (CryptographicException ex_CryptographicException)
    {
        Console.WriteLine("CryptographicException error: " + ex_CryptographicException.Message);
    }
    catch (Exception ex)
    {
        Console.WriteLine("Error: " + ex.Message);
    }

    try
    {
        cs.Close();
    }
    catch (Exception ex)
    {
        Console.WriteLine("Error by closing CryptoStream: " + ex.Message);
    }
    finally
    {
        fsOut.Close();
        fsCrypt.Close();
    }
}

如果可能的话,请提出一种实现它的方法。

标签: c#cryptographyaesfilestreamencryption-symmetric

解决方案


推荐阅读